// components.jsx — shared UI for IRON GT SERIES (i18n-aware)
const { useState, useEffect, useRef } = React;

/* ---------- config context (links the user can set in Tweaks) ---------- */
const ConfigContext = React.createContext({ discordUrl: "#discord", coffeeUrl: "#coffee", showCoffee: true });
const useCfg = () => React.useContext(ConfigContext);

/* ---------- icons ---------- */
function IconDiscord() {
  return (<svg viewBox="0 0 24 24"><path d="M19.5 5.3A17 17 0 0 0 15.3 4l-.2.4a13 13 0 0 1 3.6 1.7 12 12 0 0 0-10.3 0A13 13 0 0 1 12 4.4L11.8 4A17 17 0 0 0 7.6 5.3C4.9 9.2 4.2 13 4.5 16.8a17 17 0 0 0 5.2 2.6l.6-1a11 11 0 0 1-1.9-.9l.5-.4a12 12 0 0 0 10.2 0l.5.4c-.6.4-1.2.7-1.9.9l.6 1a17 17 0 0 0 5.2-2.6c.4-4.4-.7-8.2-3-11.5ZM9.7 14.6c-.9 0-1.6-.8-1.6-1.8s.7-1.8 1.6-1.8 1.6.8 1.6 1.8-.7 1.8-1.6 1.8Zm4.6 0c-.9 0-1.6-.8-1.6-1.8s.7-1.8 1.6-1.8 1.6.8 1.6 1.8-.7 1.8-1.6 1.8Z"/></svg>);
}
function IconPatreon() {
  return (<svg viewBox="0 0 24 24" fill="currentColor" width="16" height="16"><path d="M14.82 2.41c-3.69 0-6.68 3-6.68 6.7 0 3.68 2.99 6.68 6.68 6.68 3.69 0 6.69-3 6.69-6.68 0-3.7-3-6.7-6.69-6.7z"/><path d="M2.59 21.6h2.93V2.41H2.59z"/></svg>);
}
function IconArrow() { return (<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M5 12h14M13 6l6 6-6 6"/></svg>); }
function IconCheck() { return (<svg viewBox="0 0 24 24" fill="none" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12l5 5L20 6"/></svg>); }
function IconMenu({ open }) { return (<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">{open ? <path d="M6 6l12 12M18 6L6 18"/> : <path d="M3 6h18M3 12h18M3 18h18"/>}</svg>); }
function IconGlobe() { return (<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c2.5 2.5 2.5 15 0 18M12 3c-2.5 2.5-2.5 15 0 18"/></svg>); }

/* ---------- Discord + Patreon buttons ---------- */
function DiscordBtn({ label }) {
  const { discordUrl } = useCfg();
  return (<a className="discord" href={discordUrl} target="_blank" rel="noopener noreferrer"><IconDiscord />{label && <span className="discord-text">{label}</span>}</a>);
}
function CoffeeBtn() {
  const { coffeeUrl, showCoffee } = useCfg();
  const { t } = useT();
  if (!showCoffee) return null;
  return (<a className="coffee" href={coffeeUrl} target="_blank" rel="noopener noreferrer"><IconPatreon /><span>{t("btn.coffee")}</span></a>);
}

/* ---------- Language switcher ---------- */
function LangSwitcher() {
  const { lang, setLang } = useT();
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("click", onDoc);
    return () => document.removeEventListener("click", onDoc);
  }, []);
  const cur = LANGS.find(l => l.code === lang) || LANGS[0];
  return (
    <div className="langsw" ref={ref}>
      <button className="langbtn" onClick={() => setOpen(o => !o)} aria-label="Language">
        <IconGlobe /><b>{cur.label}</b>
        <svg width="10" height="10" viewBox="0 0 10 10" style={{ opacity: .6 }}><path d="M1 3l4 4 4-4" fill="none" stroke="currentColor" strokeWidth="1.6" /></svg>
      </button>
      {open && (
        <div className="langmenu">
          {LANGS.map(l => (
            <button key={l.code} className={l.code === lang ? "on" : ""} onClick={() => { setLang(l.code); setOpen(false); }}>
              <b>{l.label}</b><span>{l.name}</span>
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

/* ---------- Header / Nav ---------- */
function Header({ page, go }) {
  const { t } = useT();
  const [open, setOpen] = useState(false);
  return (
    <header className="hdr">
      <div className="hdr-accent" />
      <div className="hdr-in">
        <div className="brand" onClick={() => { go("home"); setOpen(false); }}>
          <div className="brand-mark"><span>IG</span></div>
          <div>
            <div className="brand-name">IRON<b>GT</b>SERIES</div>
            <div className="brand-sub">iRACING · GT3</div>
          </div>
        </div>

        <nav className={"nav" + (open ? " open" : "")}>
          {PAGE_IDS.map((id) => (
            <a key={id} className={"nav-link" + (page === id ? " active" : "")}
               onClick={() => { go(id); setOpen(false); }}>{t("nav." + id)}</a>
          ))}
        </nav>

        <div className="hdr-cta">
          <LangSwitcher />
          <CoffeeBtn />
          <DiscordBtn label="Discord" />
          <button className="nav-toggle discord" onClick={() => setOpen(o => !o)} aria-label="Menu">
            <IconMenu open={open} />
          </button>
        </div>
      </div>
    </header>
  );
}

/* ---------- Live status chip ---------- */
function LiveChip({ children }) {
  return (<span className="livechip"><span className="dot-live" />{children}</span>);
}

/* ---------- Live timing tower (decorative) ---------- */
function Tower() {
  const { t } = useT();
  return (
    <aside className="tower" aria-hidden="true">
      <div className="tower-h"><b>{t("tower.title")}</b><span>{t("tower.lap", { a: 8, b: 14 })}</span></div>
      {TOWER.map((r) => (
        <div key={r.pos} className={"tr" + (r.p1 ? " p1" : "")}>
          <div className="pos">P{r.pos}</div>
          <div className="drv"><span className="num">{r.num}</span>{r.drv}</div>
          <div className={"gap" + (r.p1 ? " purple" : "")}>{r.gap}</div>
        </div>
      ))}
      <div className="tower-foot">
        {["p","g","g","y","g","p"].map((c, i) => <div key={i} className={"secdot " + c} />)}
      </div>
    </aside>
  );
}

/* ---------- Discord community widget (custom, API-driven, free) ---------- */
const DISCORD_SERVER_ID = "1514300495802400978";
function DiscordWidget() {
  const { discordUrl } = useCfg();
  const { t } = useT();
  const [data, setData] = useState(null);
  const [err, setErr] = useState(false);

  useEffect(() => {
    fetch(`https://discord.com/api/guilds/${DISCORD_SERVER_ID}/widget.json`)
      .then(r => r.ok ? r.json() : Promise.reject())
      .then(d => setData(d))
      .catch(() => setErr(true));
  }, []);

  const members = data ? (data.members || []).slice(0, 8) : [];
  const onlineCount = data ? (data.presence_count || members.length) : null;
  const invite = (data && data.instant_invite) ? data.instant_invite : discordUrl;

  return (
    <aside className="discord-widget" aria-label="Discord Community">
      {/* Header */}
      <div className="dw-head">
        <span className="dw-live-dot" />
        <b>DISCORD HUB</b>
        <span className="dw-head-label">LIVE COMMUNITY</span>
      </div>

      {/* Body */}
      <div className="dw-body">
        {/* Server name + online count */}
        <div className="dw-server">
          <div className="dw-server-icon">
            <IconDiscord />
          </div>
          <div>
            <div className="dw-server-name">{data ? data.name : "IRON GT SERIES"}</div>
            <div className="dw-online">
              <span className="dw-dot-green" />
              {onlineCount !== null
                ? <span><b>{onlineCount}</b> {t("dw.online")}</span>
                : err ? <span style={{ color: "var(--faint)" }}>—</span>
                : <span style={{ color: "var(--faint)" }}>{t("dw.loading")}</span>
              }
            </div>
          </div>
        </div>

        {/* Online member avatars */}
        {members.length > 0 && (
          <div className="dw-members-row">
            <div className="dw-members-label">{t("dw.onlineNow")}</div>
            <div className="dw-avatars">
              {members.map((m, i) => (
                <div key={m.id || i} className="dw-avatar" title={m.username}>
                  {m.avatar_url
                    ? <img src={m.avatar_url} alt={m.username} />
                    : <span>{(m.username || "?")[0].toUpperCase()}</span>
                  }
                  <span className={`dw-status dw-status-${m.status || 'online'}`} />
                </div>
              ))}
            </div>
          </div>
        )}

        {/* Divider */}
        <div className="dw-divider" />

        {/* Info rows */}
        <div className="dw-info-rows">
          <div className="dw-info-row">
            <span className="dw-info-icon">🏎</span>
            <span>{t("dw.info1")}</span>
          </div>
          <div className="dw-info-row">
            <span className="dw-info-icon">📋</span>
            <span>{t("dw.info2")}</span>
          </div>
          <div className="dw-info-row">
            <span className="dw-info-icon">🎙</span>
            <span>{t("dw.info3")}</span>
          </div>
        </div>
      </div>

      {/* Join button */}
      <div className="dw-foot">
        <a href={invite} target="_blank" rel="noopener noreferrer" className="dw-join">
          <IconDiscord />
          <span>JOIN SERVER</span>
        </a>
      </div>
    </aside>
  );
}

/* ---------- image slot map ---------- */
function MapSlot({ id, label, shape = "rect" }) {
  const ref = useRef(null);
  useEffect(() => { if (ref.current) ref.current.setAttribute("placeholder", label); }, [label]);
  return <image-slot ref={ref} id={id} shape={shape} fit="cover"></image-slot>;
}

/* ---------- Status badge ---------- */
function StatusBadge({ status, free }) {
  const { t } = useT();
  return <span className={"status " + status}>{t("status." + status)}{status !== "full" ? ` · ${t("card.spots", { n: free })}` : ""}</span>;
}

/* ---------- Race card ---------- */
function RaceCard({ r, go }) {
  const { t, country, cond, fmtShort, fmtYear } = useT();
  const taken = r.gridTotal - r.gridFree;
  const pct = Math.round((taken / r.gridTotal) * 100);
  return (
    <article className="race reveal">
      <div className="race-map">
        <div className="race-round"><span>RND {String(r.round).padStart(2, "0")}</span></div>
        {r.imageUrl
          ? <img src={r.imageUrl} alt={r.name} style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", borderRadius: "inherit" }} />
          : <MapSlot id={"map-" + r.id} label={"CIRCUIT MAP · " + r.name.toUpperCase()} />
        }
      </div>
      <div className="race-body">
        <div className="race-top">
          <div>
            <div className="race-cc">{r.classes || r.class || r.cls || "GT3"}{r.finale ? " · " + t("sched.finale") : ""}</div>
            <h3>{r.name}</h3>
            <div className="race-loc">{cond(r.cond)}</div>
          </div>
          <StatusBadge status={r.status} free={r.gridFree} />
        </div>

        <div className="race-data">
          <div className="dcell"><div className="k">{t("card.data")}</div><div className="v">{fmtShort(r.date)}<small>{fmtYear(r.date)}</small></div></div>
          <div className="dcell"><div className="k">{t("card.start")}</div><div className="v">{r.time}<small>{r.tz} · {r.utc}</small></div></div>
          <div className="dcell"><div className="k">{t("card.race")}</div><div className="v">{r.laps} {t("card.laps")}<small>≈ {r.durMin} min</small></div></div>
          <div className="dcell"><div className="k">{t("card.grid")}</div><div className="v">{taken}/{r.gridTotal}<small>{t("card.free", { n: r.gridFree })}</small></div></div>
          {r.weather && <>
            <div className="dcell"><div className="k">{t("weather.cloud")}</div><div className="v">{r.weather.cloudCover}<small>{t("weather.track")}: {r.weather.moisture}</small></div></div>
            <div className="dcell"><div className="k">{t("weather.temp")}</div><div className="v">{r.weather.temp}°C</div></div>
            <div className="dcell"><div className="k">{t("weather.wind")}</div><div className="v">{r.weather.windSpeed} kph<small>{r.weather.windDir}</small></div></div>
            <div className="dcell"><div className="k">{t("weather.humidity")}</div><div className="v">{r.weather.humidity}%</div></div>
          </>}
        </div>

        <div className="gridbar">
          <div className="lab"><span>{t("card.occ")}</span><span>{pct}%</span></div>
          <div className="track"><div className="fill" style={{ width: pct + "%" }} /></div>
        </div>

        <div className="race-foot">
          <div className="fmt">
            {(() => {
              const pMin = r.practiceMin != null ? r.practiceMin : FORMAT.practiceMin;
              const qLaps = r.qualiLaps != null ? r.qualiLaps : FORMAT.qualiLaps;
              return <>
                {pMin > 0 && <span className="pill">{t("pill.practice")} <b>{t("val.practice", { n: pMin })}</b></span>}
                {qLaps > 0 && <span className="pill">{t("pill.quali")} <b>{t("val.qualiLaps", { n: qLaps })}</b></span>}
                <span className="pill">{t("pill.raceWord")} <b>{t("val.laps", { n: r.laps })}</b></span>
              </>;
            })()}
          </div>
          <button className="btn sm" onClick={() => go("signup", r.id)} disabled={r.status === "full"}>
            <span>{r.status === "full" ? t("btn.reserve") : t("btn.signup")}</span>
          </button>
        </div>
      </div>
    </article>
  );
}

/* ---------- Footer ---------- */
function Footer({ go }) {
  const { t } = useT();
  return (
    <footer className="footer">
      <div className="wrap footer-in">
        <div>
          <div className="brand" style={{ cursor: "default" }}>
            <div className="brand-mark"><span>IG</span></div>
            <div>
              <div className="brand-name">IRON<b>GT</b>SERIES</div>
              <div className="brand-sub">iRACING · GT3 CHAMPIONSHIP</div>
            </div>
          </div>
          <p className="muted" style={{ maxWidth: 320, marginTop: 18, fontSize: 14.5 }}>{t("footer.tagline")}</p>
          <div style={{ display: "flex", gap: 10, marginTop: 16, flexWrap: "wrap" }}>
            <DiscordBtn label={t("footer.discordBtn")} />
            <CoffeeBtn />
          </div>
        </div>
        <div className="footer-cols">
          <div className="fcol">
            <h5>{t("footer.nav")}</h5>
            {PAGE_IDS.map(id => <a key={id} onClick={() => go(id)}>{t("nav." + id)}</a>)}
          </div>
          <div className="fcol">
            <h5>{t("footer.champ")}</h5>
            <a onClick={() => go("races")}>{t("footer.calendar")}</a>
            <a onClick={() => go("about")}>{t("footer.formatRules")}</a>
            <a onClick={() => go("signup")}>{t("footer.signupRound")}</a>
            <DiscordLink label={t("footer.results")} />
          </div>
          <div className="fcol">
            <h5>{t("footer.community")}</h5>
            <DiscordLink label={t("footer.discordLink")} />
            <a href="#">{t("footer.twitch")}</a>
            <a onClick={() => go("about")}>{t("footer.coc")}</a>
          </div>
        </div>
      </div>
      <div className="wrap">
        <div className="footer-bot">
          <span>{t("footer.bottom1")}</span>
          <span>{t("footer.bottom2")}</span>
        </div>
      </div>
    </footer>
  );
}
function DiscordLink({ label }) {
  const { discordUrl } = useCfg();
  return <a href={discordUrl} target="_blank" rel="noopener noreferrer">{label}</a>;
}

/* ---------- Ticker ---------- */
function Ticker({ races }) {
  const { t, fmtShort } = useT();
  const list = races || [];
  const upcoming = list.filter(r => r.status !== 'done');
  const next = upcoming[0];
  const filling = upcoming.filter(r => r.status === 'filling' && r !== next);

  const items = [];
  if (list.length === 0) {
    items.push(t("ticker.soon1"));
    items.push(t("ticker.soon2"));
    items.push(t("ticker.soon3"));
    items.push(t("ticker.soon4"));
  } else {
    if (next) {
      items.push(t("ticker.next", { name: next.name.toUpperCase(), rnd: String(next.round).padStart(2,"0"), date: fmtShort(next.date), time: next.time, tz: next.tz }));
      if (next.gridFree > 0) items.push(t("ticker.spots", { n: next.gridFree, name: next.name.toUpperCase() }));
    }
    filling.forEach(r => items.push(t("ticker.filling", { name: r.name.toUpperCase(), rnd: String(r.round).padStart(2,"0"), n: r.gridFree })));
    items.push(t("ticker.format", { q: (window.FORMAT && FORMAT.qualiLaps) || 3 }));
    items.push(t("ticker.season", { y: SEASON.year, n: list.length }));
    items.push(t("ticker.clean"));
  }

  const doubled = [...items, ...items];
  const rendered = doubled.map((s, i) => <span key={i} className="ticker-item" dangerouslySetInnerHTML={{ __html: s }} />);
  return (
    <div className="ticker">
      <div className="ticker-lab">● LIVE</div>
      <div className="ticker-track">{rendered}</div>
    </div>
  );
}

Object.assign(window, {
  Header, Footer, Ticker, Tower, DiscordWidget, RaceCard, LiveChip, MapSlot, StatusBadge,
  DiscordBtn, CoffeeBtn, DiscordLink, LangSwitcher,
  IconDiscord, IconCoffee, IconArrow, IconCheck, IconGlobe,
  ConfigContext, useCfg,
});
