// OpenF1 + Jolpica live data integration
// Fetches real F1 session data and maps it to the app's data model.
// No auth required. Free APIs.

const { useState: useStateF1, useEffect: useEffectF1, useRef: useRefF1, useCallback: useCbF1 } = React;

const OPENF1 = "https://api.openf1.org/v1";
const JOLPICA = "https://api.jolpi.ca/ergast/f1";

window.F1_MODE = { active: false };

async function f1Fetch(url) {
  try {
    const r = await fetch(url);
    if (!r.ok) return null;
    return r.json();
  } catch { return null; }
}

// Map OpenF1 driver data to our app's car format
function mapDriverToCar(driver, position, interval, stint, idx) {
  const teamColors = {
    "Red Bull Racing": { primary: "#3671C6", secondary: "#FFD700", accent: "#FFD700" },
    "McLaren": { primary: "#FF8000", secondary: "#000000", accent: "#FF8000" },
    "Ferrari": { primary: "#E80020", secondary: "#FFFF00", accent: "#E80020" },
    "Mercedes": { primary: "#27F4D2", secondary: "#000000", accent: "#27F4D2" },
    "Aston Martin": { primary: "#229971", secondary: "#FFFFFF", accent: "#229971" },
    "Alpine": { primary: "#FF87BC", secondary: "#0093CC", accent: "#FF87BC" },
    "Williams": { primary: "#64C4FF", secondary: "#FFFFFF", accent: "#64C4FF" },
    "RB": { primary: "#6692FF", secondary: "#FFFFFF", accent: "#6692FF" },
    "Kick Sauber": { primary: "#52E252", secondary: "#000000", accent: "#52E252" },
    "Haas F1 Team": { primary: "#B6BABD", secondary: "#E80020", accent: "#B6BABD" },
  };

  const teamKey = Object.keys(teamColors).find(k =>
    driver.team_name && driver.team_name.includes(k.split(" ")[0])
  );
  const livery = teamColors[teamKey] || { primary: "#555", secondary: "#999", accent: "#888", pattern: "solid" };
  livery.pattern = "stripe-diag";

  const pos = position ? position.position : idx + 1;
  const gap = pos === 1 ? "LEADER" : (interval && interval.gap_to_leader ? `+${interval.gap_to_leader}` : `+${(pos * 0.8).toFixed(3)}`);
  const compound = stint ? stint.compound : "M";
  const tireMap = { SOFT: "S", MEDIUM: "M", HARD: "H", INTERMEDIATE: "I", WET: "W" };

  return {
    no: driver.driver_number,
    pos,
    name: driver.full_name || `Driver ${driver.driver_number}`,
    country: driver.country_code || "---",
    age: 0,
    team: driver.team_name || "Unknown",
    short: (driver.name_acronym || "UNK").toUpperCase(),
    livery,
    chassis: "F1 2026",
    engine: driver.team_name || "PU",
    crew_chief: "",
    race_engineer: "",
    sponsors: { title: driver.team_name || "", primary: [], support: [] },
    bio: "",
    helmet: { primary: livery.primary, secondary: livery.secondary, visor: "#333" },
    last_lap: "---",
    best_lap: "---",
    gap,
    tire: tireMap[compound] || "M",
    tire_age: stint ? (stint.tyre_age_at_start || 0) : 0,
    fuel: 100,
    sectors: [
      { s: "S1", t: "---", state: "green" },
      { s: "S2", t: "---", state: "green" },
      { s: "S3", t: "---", state: "green" },
    ],
    _headshot: driver.headshot_url || null,
    _teamColor: driver.team_colour ? `#${driver.team_colour}` : livery.accent,
  };
}

function F1DataProvider({ children, onData, sessionKey }) {
  const [status, setStatus] = useStateF1("idle");
  const [session, setSession] = useStateF1(null);
  const pollRef = useRefF1(null);

  const fetchSession = useCbF1(async () => {
    setStatus("connecting");
    const key = sessionKey || "latest";
    const sessions = await f1Fetch(`${OPENF1}/sessions?session_key=${key}`);
    if (!sessions || !sessions.length) { setStatus("no-session"); return; }
    const s = sessions[sessions.length - 1];
    setSession(s);
    setStatus("connected");
    return s;
  }, [sessionKey]);

  const fetchLiveData = useCbF1(async (sKey) => {
    const [drivers, positions, intervals, stints, laps, pit, weather, raceControl] = await Promise.all([
      f1Fetch(`${OPENF1}/drivers?session_key=${sKey}`),
      f1Fetch(`${OPENF1}/position?session_key=${sKey}`),
      f1Fetch(`${OPENF1}/intervals?session_key=${sKey}`),
      f1Fetch(`${OPENF1}/stints?session_key=${sKey}`),
      f1Fetch(`${OPENF1}/laps?session_key=${sKey}&driver_number=1`),
      f1Fetch(`${OPENF1}/pit?session_key=${sKey}`),
      f1Fetch(`${OPENF1}/weather?session_key=${sKey}`),
      f1Fetch(`${OPENF1}/race_control?session_key=${sKey}`),
    ]);

    if (!drivers || !drivers.length) return null;

    // Dedupe drivers by number (API returns one entry per session appearance)
    const driverMap = {};
    drivers.forEach(d => { driverMap[d.driver_number] = d; });
    const uniqueDrivers = Object.values(driverMap);

    // Latest position per driver
    const latestPos = {};
    if (positions) positions.forEach(p => { latestPos[p.driver_number] = p; });

    // Latest interval per driver
    const latestInt = {};
    if (intervals) intervals.forEach(i => { latestInt[i.driver_number] = i; });

    // Latest stint per driver
    const latestStint = {};
    if (stints) stints.forEach(s => { latestStint[s.driver_number] = s; });

    const cars = uniqueDrivers.map((d, idx) =>
      mapDriverToCar(d, latestPos[d.driver_number], latestInt[d.driver_number], latestStint[d.driver_number], idx)
    ).sort((a, b) => a.pos - b.pos);

    // Latest weather
    const w = weather && weather.length ? weather[weather.length - 1] : null;

    // Latest race control (flag)
    const rc = raceControl && raceControl.length ? raceControl[raceControl.length - 1] : null;
    let flag = "green";
    if (rc) {
      if (rc.flag === "RED") flag = "red";
      else if (rc.flag === "YELLOW" || rc.category === "SafetyCar") flag = "yellow";
      else if (rc.flag === "CHEQUERED") flag = "checkered";
    }

    // Current lap (from the latest lap entry)
    const currentLap = laps && laps.length ? laps[laps.length - 1].lap_number : 0;

    // Update lap times from laps data
    if (laps && laps.length) {
      const lapsByDriver = {};
      laps.forEach(l => {
        if (!lapsByDriver[l.driver_number]) lapsByDriver[l.driver_number] = [];
        lapsByDriver[l.driver_number].push(l);
      });
    }

    return {
      cars,
      weather: w ? {
        air_c: w.air_temperature,
        track_c: w.track_temperature,
        wind_kph: w.wind_speed,
        condition: w.rainfall ? "WET" : "DRY",
        humidity: w.humidity,
      } : null,
      flag,
      lap: currentLap,
      pitStops: pit || [],
      session: session,
    };
  }, [session]);

  useEffectF1(() => {
    if (status !== "connected" || !session) return;
    let active = true;

    const poll = async () => {
      const data = await fetchLiveData(session.session_key);
      if (data && active && onData) onData(data);
    };
    poll();
    pollRef.current = setInterval(poll, 8000); // poll every 8s

    return () => { active = false; clearInterval(pollRef.current); };
  }, [status, session, fetchLiveData, onData]);

  return React.createElement("div", { className: "f1-provider" },
    React.createElement("div", { className: "f1-status f1-status-" + status },
      status === "idle" && React.createElement("button", {
        className: "f1-connect-btn",
        onClick: fetchSession
      }, "CONNECT TO LIVE F1"),
      status === "connecting" && "CONNECTING TO OPENF1…",
      status === "no-session" && React.createElement("span", null,
        "NO LIVE SESSION ",
        React.createElement("button", { className: "f1-retry-btn", onClick: fetchSession }, "RETRY")
      ),
      status === "connected" && session && React.createElement("span", { className: "f1-live-tag" },
        React.createElement("span", { className: "bc-dot" }),
        " LIVE · ", session.session_name, " · ", session.circuit_short_name
      )
    ),
    children
  );
}

// Fetch upcoming F1 schedule from Jolpica
async function fetchF1Schedule() {
  const data = await f1Fetch(`${JOLPICA}/current.json`);
  if (!data || !data.MRData) return [];
  const races = data.MRData.RaceTable.Races;
  return races.map(r => ({
    round: r.round,
    name: r.raceName,
    circuit: r.Circuit.circuitName,
    country: r.Circuit.Location.country,
    date: r.date,
    time: r.time,
  }));
}

window.F1DataProvider = F1DataProvider;
window.fetchF1Schedule = fetchF1Schedule;
window.f1Fetch = f1Fetch;
window.OPENF1_BASE = OPENF1;
