/* Formula Destruction — shared React atoms. Exported to window. */
const { useState, useEffect, useRef } = React;

/* ----------------------------------------------------------------- FLAGS
   Real flag SVGs from flagcdn.com, keyed by ISO 3166-1 alpha-2 code.
   Wrapped with rounded corners + shadow so they read crisply at any size.
   Falls back to a country-code chip for an empty/unknown code or a load
   failure (e.g. offline). */
function Flag({ code, w = 22 }) {
  const [failed, setFailed] = useState(false);
  const cc = (code || "").toLowerCase();
  const h = Math.round(w * 0.68);
  const wrap = {
    width: w, height: h, borderRadius: 3, overflow: "hidden", flex: "none",
    boxShadow: "inset 0 0 0 1px rgba(255,255,255,.18), 0 1px 2px rgba(0,0,0,.4)",
    display: "inline-block", position: "relative", background: "#222",
  };
  if (cc && !failed) {
    return <img
      src={`https://flagcdn.com/${cc}.svg`}
      alt={(code || "").toUpperCase()}
      width={w} height={h}
      onError={() => setFailed(true)}
      style={{ ...wrap, objectFit: "cover" }}
    />;
  }
  // fallback chip — empty code or image failed to load
  return <span style={{ ...wrap, width: "auto", padding: "0 5px", height: h, display: "inline-flex", alignItems: "center",
    fontFamily: "var(--mono)", fontSize: 9, letterSpacing: ".06em", color: "#cfd6e0", background: "#2a3140" }}>{(code || "??").toUpperCase()}</span>;
}

/* --------------------------------------------------------------- AVATAR
   Initials on a team-tinted gradient. Drop real photos in later. */
function Avatar({ driver, size = 44, ring = true }) {
  const FD = window.FD;
  // driver.team is the current-season team (null for drivers not racing now);
  // fall back to their most recent team, then to a neutral grey.
  let team = FD.teamById[driver.team];
  if (!team && driver.hist) {
    for (const s of FD.seasons) { if (driver.hist[s.id]) { team = FD.teamById[driver.hist[s.id]]; break; } }
  }
  team = team || { color: "#555" };
  const initials = (driver.code || driver.username.slice(0, 2)).toUpperCase();
  const ringShadow = ring ? `inset 0 0 0 2px rgba(255,255,255,.14), 0 0 0 2px color-mix(in srgb, ${team.color} 55%, transparent)` : "inset 0 0 0 1px rgba(255,255,255,.12)";
  if (driver.photoUrl) {
    return (
      <img src={driver.photoUrl} alt={driver.username} style={{
        width: size, height: size, borderRadius: "50%", flex: "none",
        objectFit: "cover", display: "inline-block",
        boxShadow: ringShadow,
      }} />
    );
  }
  return (
    <span style={{
      width: size, height: size, borderRadius: "50%", flex: "none",
      display: "inline-flex", alignItems: "center", justifyContent: "center",
      fontFamily: "var(--display)", fontWeight: 700, fontSize: size * (initials.length > 2 ? 0.32 : 0.4),
      color: "#fff", letterSpacing: "-.02em",
      background: `radial-gradient(120% 120% at 30% 20%, ${team.color}, color-mix(in srgb, ${team.color} 30%, #0a0c10) 90%)`,
      boxShadow: ringShadow,
    }}>{initials}</span>
  );
}

/* ------------------------------------------------------------ TEAM LOGO
   A team's logo image when one is set, else a color-tinted chip showing the
   team code. `size` is the box edge in px. Used everywhere a team is shown
   prettily — cards, standings, hero blocks — and degrades gracefully if the
   image is missing or fails to load. */
function TeamLogo({ team, size = 28, radius }) {
  const [failed, setFailed] = useState(false);
  const t = team || {};
  const color = t.color || "#555";
  const r = radius == null ? Math.round(size * 0.28) : radius;
  const box = {
    width: size, height: size, borderRadius: r, flex: "none", overflow: "hidden",
    display: "inline-flex", alignItems: "center", justifyContent: "center",
    boxShadow: "inset 0 0 0 1px rgba(255,255,255,.12)",
  };
  if (t.logoUrl && !failed) {
    // F1 marks are designed for light backgrounds (Ferrari, Sauber, Mercedes,
    // McLaren are dark-on-white). A clean white plate gives every logo contrast
    // and hides the baked-in white rectangles some sources ship. The logo fills
    // the padded plate by its longest side, so wide wordmarks aren't shrunk to
    // fit a square.
    return (
      <span style={{ ...box,
        background: "linear-gradient(155deg, #ffffff, #e9ebf0)",
        boxShadow: "inset 0 0 0 1px rgba(255,255,255,.6), 0 2px 6px rgba(0,0,0,.35)",
        padding: Math.max(3, Math.round(size * 0.1)) }}>
        <img src={t.logoUrl} alt={t.name || t.code || "team"} onError={() => setFailed(true)}
          style={{ maxWidth: "100%", maxHeight: "100%", width: "auto", height: "auto",
            objectFit: "contain", display: "block" }} />
      </span>
    );
  }
  const initials = (t.code || t.name || "??").slice(0, 3).toUpperCase();
  return (
    <span style={{ ...box,
      fontFamily: "var(--display)", fontWeight: 700, fontSize: size * (initials.length > 2 ? 0.3 : 0.38),
      color: "#fff", letterSpacing: "-.02em",
      background: `radial-gradient(120% 120% at 30% 20%, ${color}, color-mix(in srgb, ${color} 30%, #0a0c10) 90%)` }}>
      {initials}
    </span>
  );
}

/* ------------------------------------------------------------- COUNTDOWN */
function useCountdown(target) {
  const [now, setNow] = useState(Date.now());
  useEffect(() => { const id = setInterval(() => setNow(Date.now()), 1000); return () => clearInterval(id); }, []);
  let diff = Math.max(0, new Date(target).getTime() - now);
  const d = Math.floor(diff / 864e5); diff -= d * 864e5;
  const h = Math.floor(diff / 36e5);  diff -= h * 36e5;
  const m = Math.floor(diff / 6e4);   diff -= m * 6e4;
  const s = Math.floor(diff / 1e3);
  return { d, h, m, s };
}

/* --------------------------------------------------------- ANIMATED NUMBER */
function AnimatedNumber({ value, duration = 1100, className, style }) {
  const [n, setN] = useState(0);
  const ref = useRef();
  useEffect(() => {
    const start = performance.now(); const from = 0; const to = value;
    cancelAnimationFrame(ref.current);
    const tick = (t) => {
      const p = Math.min(1, (t - start) / duration);
      const e = 1 - Math.pow(1 - p, 3);
      setN(Math.round(from + (to - from) * e));
      if (p < 1) ref.current = requestAnimationFrame(tick);
    };
    ref.current = requestAnimationFrame(tick);
    // safety: guarantee the final value even if rAF is throttled (hidden frame)
    const guard = setTimeout(() => setN(to), duration + 400);
    return () => { cancelAnimationFrame(ref.current); clearTimeout(guard); };
  }, [value]);
  return <span className={className} style={style}>{n.toLocaleString()}</span>;
}

/* ---------------------------------------------------------------- LOGO
   Typographic lockup + simple angular mark (no fragile illustration). */
function Mark({ size = 26, color = "var(--accent)" }) {
  return (
    <span style={{ display: "inline-flex", gap: size * 0.12, height: size, alignItems: "stretch", flex: "none" }}>
      {[1, 0.62, 0.30].map((op, i) => (
        <span key={i} style={{ width: size * 0.2, background: color, opacity: op, transform: "skewX(-16deg)", borderRadius: 1 }} />
      ))}
    </span>
  );
}
function Logo({ size = 22, stacked = false, color = "var(--ink)" }) {
  // Brand wordmark (orange "Formula Destruction" lockup). `size` keeps its
  // original meaning as the type height; the stacked two-line lockup renders
  // at ~1.6x that. `stacked`/`color` are accepted for call-site compatibility.
  return (
    <img
      src="/assets/wordmark.png"
      alt="Formula Destruction"
      style={{ height: size * 1.6, width: "auto", display: "block", flex: "none" }}
    />
  );
}

Object.assign(window, { Flag, Avatar, TeamLogo, useCountdown, AnimatedNumber, Mark, Logo });
