/* World Cup 2026 Prediction Pool — frontend (talks to /api on the same server) */
const { useState, useEffect, useMemo } = React;

const C = {
  bg:"#0B1220", panel:"#121C2E", panel2:"#0F1726", line:"#22304A",
  text:"#E9EEF6", mute:"#8A97AB", green:"#34C26B", greenDk:"#1C7A45",
  gold:"#E8B33C", red:"#E0635F",
};
const display = { fontFamily:'"Arial Black", "Avenir Next Condensed", Impact, sans-serif', letterSpacing:"0.5px" };
const eyebrow = { fontSize:11, letterSpacing:"2.5px", textTransform:"uppercase", color:C.mute, fontWeight:700 };
const emailOk = (e) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e);
const outcomeOf = (r) => (r.h > r.a ? "H" : r.h < r.a ? "A" : "D");
// All times are rendered with the browser's own locale + timezone,
// so every teammate sees kickoffs in their local time automatically.
const TZ = Intl.DateTimeFormat().resolvedOptions().timeZone;
const fmtDate = (d) => new Date(d + "T12:00:00Z").toLocaleDateString(undefined, { weekday:"short", day:"numeric", month:"short" });
const fmtKO = (m) => m.ko
  ? new Date(m.ko).toLocaleString(undefined, { weekday:"short", day:"numeric", month:"short", hour:"numeric", minute:"2-digit" })
  : fmtDate(m.date) + " · time TBC";
const kickoffPassed = (m, today) => m.ko ? Date.now() >= new Date(m.ko).getTime() : today >= m.date;

async function api(path, opts) {
  const r = await fetch(path, opts ? { method:"POST", headers:{ "Content-Type":"application/json" }, body: JSON.stringify(opts) } : undefined);
  const data = await r.json().catch(() => ({}));
  if (!r.ok) throw new Error(data.error || "Request failed");
  return data;
}

function App() {
  const [tab, setTab] = useState("predict");
  const [name, setName] = useState(localStorage.getItem("wc_name") || "");
  const [email, setEmail] = useState(localStorage.getItem("wc_email") || "");
  const [user, setUser] = useState(null);
  const [isAdmin, setIsAdmin] = useState(false);
  const [state, setState] = useState(null); // {matches, rounds, results, board, today}
  const [pending, setPending] = useState({});
  const [confirming, setConfirming] = useState(false);
  const [busy, setBusy] = useState("");
  const [msg, setMsg] = useState("");
  const [err, setErr] = useState("");
  const [adminScores, setAdminScores] = useState({});

  async function refresh(em) {
    try {
      const s = await api("/api/state?email=" + encodeURIComponent(em || user?.email || ""));
      setState(s);
      if (s.me) setUser(s.me);
      setIsAdmin(s.isAdmin);
    } catch { /* server offline */ }
  }
  useEffect(() => { refresh(email); const t = setInterval(() => refresh(), 60000); return () => clearInterval(t); }, []);

  async function join() {
    setErr(""); setMsg("");
    if (!name.trim()) return setErr("Enter your name.");
    if (!emailOk(email.trim())) return setErr("Enter a valid email address.");
    setBusy("join");
    try {
      const r = await api("/api/join", { name: name.trim(), email: email.trim() });
      setUser(r.me); setIsAdmin(r.isAdmin);
      localStorage.setItem("wc_name", name.trim());
      localStorage.setItem("wc_email", email.trim().toLowerCase());
      const n = Object.keys(r.me.preds || {}).length;
      setMsg(n ? `Welcome back, ${r.me.name}. ${n} prediction(s) on record — those are locked.` :
        "You're in! Pick your winners below. Every submitted pick is final.");
      refresh(email.trim());
    } catch (e) { setErr(e.message); }
    setBusy("");
  }

  const matches = state?.matches || [];
  const rounds = state?.rounds || [];
  const results = state?.results || {};
  const today = state?.today || new Date().toISOString().slice(0, 10);
  const unlockedMap = Object.fromEntries(rounds.map((r) => [r.n, r.unlocked]));
  const matchPickable = (m) =>
    user && unlockedMap[m.round] && !results[m.id] && !kickoffPassed(m, today) && !(user.preds || {})[m.id];

  async function submitPicks() {
    const picks = Object.fromEntries(Object.entries(pending).filter(([, v]) => v));
    if (!Object.keys(picks).length) return;
    setBusy("submit"); setErr(""); setMsg("");
    try {
      const r = await api("/api/predict", { email: user.email, picks });
      setUser(r.me); setPending({}); setConfirming(false);
      setMsg(`${r.added} prediction(s) locked in.` + (r.skipped ? ` ${r.skipped} skipped (already submitted or closed).` : ""));
      refresh();
    } catch (e) { setErr(e.message); }
    setBusy("");
  }

  async function checkLive() {
    setBusy("results"); setErr(""); setMsg("");
    try {
      const r = await api("/api/refresh-results", {});
      setMsg(r.added ? `Updated ${r.added} result(s). Leaderboard refreshed.` : "No new final scores yet — try again after matches finish.");
      refresh();
    } catch (e) { setErr(e.message); }
    setBusy("");
  }

  async function adminSave(m) {
    const v = adminScores[m.id] || {};
    setBusy("admin"); setErr("");
    try {
      await api("/api/result", { email: user.email, matchId: m.id, h: v.h, a: v.a });
      setMsg(`Result saved for ${m.home.name} vs ${m.away.name}.`);
      refresh();
    } catch (e) { setErr(e.message); }
    setBusy("");
  }

  const board = state?.board || [];
  const myScore = user ? board.find((b) => b.name === user.name && b.total === Object.keys(user.preds || {}).length) : null;
  const stagedCount = Object.values(pending).filter(Boolean).length;

  const Btn = ({ on, children, ...p }) => (
    <button {...p} style={{
      flex:1, padding:"9px 4px", borderRadius:8, border:`1px solid ${on ? C.green : C.line}`,
      background: on ? C.green : C.panel2, color: on ? "#06200F" : C.text,
      fontWeight:700, fontSize:13, cursor: p.disabled ? "default" : "pointer",
      opacity: p.disabled && !on ? 0.45 : 1, ...p.style }}>{children}</button>
  );

  function MatchCard({ m }) {
    const res = results[m.id];
    const myPick = (user?.preds || {})[m.id]?.pick;
    const staged = pending[m.id];
    const pickable = matchPickable(m);
    const closed = !res && (kickoffPassed(m, today) || !unlockedMap[m.round]);
    const correct = res && myPick ? myPick === outcomeOf(res) : null;
    const setPick = (v) => pickable && setPending((p) => ({ ...p, [m.id]: p[m.id] === v ? undefined : v }));
    return (
      <div style={{ background:C.panel, border:`1px solid ${staged ? C.green : C.line}`, borderRadius:12, padding:"12px 14px" }}>
        <div style={{ display:"flex", justifyContent:"space-between", marginBottom:8 }}>
          <span style={eyebrow}>Group {m.g} · {fmtKO(m)}</span>
          {res ? <span style={{ fontSize:11, fontWeight:800, color: correct === null ? C.mute : correct ? C.green : C.red }}>FT {res.h}–{res.a}{correct === true ? " ✓ +1" : correct === false ? " ✗" : ""}</span>
            : myPick ? <span style={{ fontSize:11, fontWeight:800, color:C.gold }}>🔒 LOCKED</span>
            : closed ? <span style={{ fontSize:11, fontWeight:800, color:C.mute }}>CLOSED</span> : null}
        </div>
        <div style={{ display:"flex", alignItems:"center", justifyContent:"space-between", marginBottom:10 }}>
          <div style={{ display:"flex", alignItems:"center", gap:8, width:"42%" }}>
            <span style={{ fontSize:22 }}>{m.home.flag}</span><span style={{ fontWeight:700, fontSize:14 }}>{m.home.name}</span>
          </div>
          <span style={{ ...display, color:C.mute, fontSize:12 }}>{res ? `${res.h} : ${res.a}` : "VS"}</span>
          <div style={{ display:"flex", alignItems:"center", gap:8, width:"42%", justifyContent:"flex-end" }}>
            <span style={{ fontWeight:700, fontSize:14, textAlign:"right" }}>{m.away.name}</span><span style={{ fontSize:22 }}>{m.away.flag}</span>
          </div>
        </div>
        <div style={{ display:"flex", gap:6 }}>
          <Btn on={myPick === "H" || staged === "H"} disabled={!pickable} onClick={() => setPick("H")}>{m.home.name} win</Btn>
          <Btn on={myPick === "D" || staged === "D"} disabled={!pickable} onClick={() => setPick("D")} style={{ flex:0.6 }}>Draw</Btn>
          <Btn on={myPick === "A" || staged === "A"} disabled={!pickable} onClick={() => setPick("A")}>{m.away.name} win</Btn>
        </div>
      </div>
    );
  }

  return (
    <div style={{ minHeight:"100vh", background:C.bg, color:C.text, fontFamily:"system-ui, -apple-system, sans-serif", paddingBottom:90 }}>
      <div style={{ background:`linear-gradient(135deg, ${C.greenDk} 0%, #0E3B24 55%, ${C.bg} 100%)`, padding:"26px 18px 20px", borderBottom:`1px solid ${C.line}` }}>
        <div style={{ maxWidth:880, margin:"0 auto" }}>
          <div style={eyebrow}>FIFA World Cup 2026 · Group Stage · Office Pool</div>
          <h1 style={{ ...display, fontSize:30, margin:"6px 0 4px", color:"#fff" }}>⚽ PREDICT &amp; WIN</h1>
          <div style={{ color:"#CFE7D8", fontSize:13 }}>72 matches · 1 point per correct call · picks are <b>final once submitted</b></div>
          <div style={{ ...eyebrow, marginTop:6, color:"#9FC4AD" }}>🕐 All kickoff times shown in your local time ({TZ})</div>
        </div>
      </div>

      <div style={{ maxWidth:880, margin:"0 auto", padding:"16px 14px" }}>
        {!user ? (
          <div style={{ background:C.panel, border:`1px solid ${C.line}`, borderRadius:14, padding:18, marginBottom:18 }}>
            <div style={{ ...eyebrow, marginBottom:10 }}>Step 1 — Identify yourself</div>
            <div style={{ display:"flex", gap:8, flexWrap:"wrap" }}>
              <input placeholder="Your name" value={name} onChange={(e) => setName(e.target.value)}
                style={{ flex:"1 1 160px", padding:"11px 12px", borderRadius:9, border:`1px solid ${C.line}`, background:C.panel2, color:C.text, fontSize:14 }} />
              <input placeholder="Work email" value={email} onChange={(e) => setEmail(e.target.value)}
                style={{ flex:"2 1 220px", padding:"11px 12px", borderRadius:9, border:`1px solid ${C.line}`, background:C.panel2, color:C.text, fontSize:14 }} />
              <button onClick={join} disabled={busy === "join"}
                style={{ padding:"11px 22px", borderRadius:9, border:"none", background:C.green, color:"#06200F", fontWeight:800, fontSize:14, cursor:"pointer" }}>
                {busy === "join" ? "Joining…" : "Enter the pool"}
              </button>
            </div>
            <div style={{ fontSize:12, color:C.mute, marginTop:10 }}>
              Your email is your identity — once a prediction is submitted under it, it cannot be changed by anyone.
            </div>
          </div>
        ) : (
          <div style={{ display:"flex", alignItems:"center", justifyContent:"space-between", background:C.panel, border:`1px solid ${C.line}`, borderRadius:12, padding:"10px 14px", marginBottom:14, flexWrap:"wrap", gap:8 }}>
            <div style={{ fontSize:14 }}><b>{user.name}</b> <span style={{ color:C.mute }}>({user.email}{isAdmin ? " · admin" : ""})</span></div>
            <div style={{ fontSize:13, color:C.gold, fontWeight:800 }}>{myScore ? `★ ${myScore.pts} pts · ${myScore.total} picks made` : ""}</div>
          </div>
        )}

        {(msg || err) && (
          <div style={{ background: err ? "#3A1B1B" : "#11301F", border:`1px solid ${err ? C.red : C.green}`, color: err ? "#F3C2C0" : "#C9EFD8", borderRadius:10, padding:"10px 13px", fontSize:13, marginBottom:14 }}>{err || msg}</div>
        )}

        <div style={{ display:"flex", gap:6, marginBottom:16, flexWrap:"wrap" }}>
          {[["predict","Predictions"],["board","🏆 Leaderboard"],["results","Results"]].map(([k, label]) => (
            <button key={k} onClick={() => setTab(k)}
              style={{ padding:"9px 16px", borderRadius:9, border:`1px solid ${tab === k ? C.green : C.line}`, background: tab === k ? C.green : C.panel, color: tab === k ? "#06200F" : C.text, fontWeight:800, fontSize:13, cursor:"pointer" }}>{label}</button>
          ))}
          <button onClick={checkLive} disabled={busy === "results"}
            style={{ marginLeft:"auto", padding:"9px 14px", borderRadius:9, border:`1px solid ${C.gold}`, background:"transparent", color:C.gold, fontWeight:800, fontSize:13, cursor:"pointer" }}>
            {busy === "results" ? "Checking…" : "⟳ Check live results"}
          </button>
          {isAdmin && (
            <button onClick={async () => { setBusy("sync"); setErr(""); try { const r = await api("/api/sync-schedule", { email: user.email }); setMsg(`Schedule synced — ${r.total ?? 0} official kickoff times known (${r.synced} updated).`); refresh(); } catch (e) { setErr(e.message); } setBusy(""); }} disabled={busy === "sync"}
              style={{ padding:"9px 14px", borderRadius:9, border:`1px solid ${C.line}`, background:"transparent", color:C.mute, fontWeight:800, fontSize:13, cursor:"pointer" }}>
              {busy === "sync" ? "Syncing…" : "🗓 Sync schedule"}
            </button>
          )}
        </div>

        {tab === "predict" && rounds.map((r) => {
          const ms = matches.filter((m) => m.round === r.n);
          const done = ms.filter((m) => results[m.id]).length;
          return (
            <div key={r.n} style={{ marginBottom:26 }}>
              <div style={{ display:"flex", alignItems:"baseline", gap:10, marginBottom:10 }}>
                <h2 style={{ ...display, fontSize:19, margin:0, color: r.unlocked ? "#fff" : C.mute }}>{r.unlocked ? "" : "🔒 "}{r.title}</h2>
                <span style={eyebrow}>{r.dates} · {done}/{ms.length} played</span>
              </div>
              {!r.unlocked ? (
                <div style={{ background:C.panel2, border:`1px dashed ${C.line}`, borderRadius:12, padding:"16px 14px", color:C.mute, fontSize:13 }}>
                  Opens when every {rounds[r.n - 2]?.title} result is in (or on {fmtDate(r.start)}).
                </div>
              ) : (
                <div style={{ display:"grid", gridTemplateColumns:"repeat(auto-fill, minmax(290px, 1fr))", gap:10 }}>
                  {ms.map((m) => <MatchCard key={m.id} m={m} />)}
                </div>
              )}
            </div>
          );
        })}

        {tab === "board" && (
          <div style={{ background:C.panel, border:`1px solid ${C.line}`, borderRadius:14, overflow:"hidden" }}>
            <div style={{ padding:"14px 16px", borderBottom:`1px solid ${C.line}` }}><div style={eyebrow}>Live standings — 1 point per correct result</div></div>
            {board.length === 0 ? <div style={{ padding:24, color:C.mute, fontSize:14 }}>No players yet. Be the first!</div> :
              board.map((p, i) => (
                <div key={p.emailMasked + i} style={{ display:"flex", alignItems:"center", gap:12, padding:"12px 16px", borderBottom:`1px solid ${C.line}`, background: i === 0 && p.pts > 0 ? "rgba(232,179,60,0.08)" : "transparent" }}>
                  <span style={{ ...display, width:34, color: i === 0 ? C.gold : C.mute, fontSize:15 }}>{i === 0 && p.pts > 0 ? "👑" : `#${i + 1}`}</span>
                  <span style={{ flex:1, fontWeight:700, fontSize:14 }}>{p.name} <span style={{ color:C.mute, fontSize:11 }}>{p.emailMasked}</span></span>
                  <span style={{ fontSize:12, color:C.mute }}>{p.played} graded / {p.total} picks</span>
                  <span style={{ ...display, color: i === 0 && p.pts > 0 ? C.gold : C.text, fontSize:18, width:44, textAlign:"right" }}>{p.pts}</span>
                </div>
              ))}
          </div>
        )}

        {tab === "results" && rounds.map((r) => (
          <div key={r.n} style={{ marginBottom:22 }}>
            <h3 style={{ ...display, fontSize:16, margin:"0 0 8px" }}>{r.title} <span style={eyebrow}>· {r.dates}</span></h3>
            {matches.filter((m) => m.round === r.n).map((m) => {
              const res = results[m.id];
              return (
                <div key={m.id} style={{ display:"flex", alignItems:"center", gap:10, background:C.panel, border:`1px solid ${C.line}`, borderRadius:10, padding:"9px 12px", marginBottom:6, fontSize:13, flexWrap:"wrap" }}>
                  <span style={{ ...eyebrow, width:120 }}>Grp {m.g} · {fmtKO(m)}</span>
                  <span style={{ flex:1, minWidth:200 }}>{m.home.flag} {m.home.name} <b style={{ color: res ? C.green : C.mute }}>{res ? `${res.h} – ${res.a}` : "vs"}</b> {m.away.name} {m.away.flag}</span>
                  {res ? <span style={{ fontSize:11, fontWeight:800, color:C.green }}>FINAL</span> :
                    isAdmin && kickoffPassed(m, today) ? (
                      <span style={{ display:"flex", gap:5, alignItems:"center" }}>
                        <input type="number" min="0" placeholder="H" value={adminScores[m.id]?.h ?? ""} onChange={(e) => setAdminScores((s) => ({ ...s, [m.id]: { ...s[m.id], h: e.target.value } }))}
                          style={{ width:42, padding:"5px 6px", borderRadius:6, border:`1px solid ${C.line}`, background:C.panel2, color:C.text }} />
                        <input type="number" min="0" placeholder="A" value={adminScores[m.id]?.a ?? ""} onChange={(e) => setAdminScores((s) => ({ ...s, [m.id]: { ...s[m.id], a: e.target.value } }))}
                          style={{ width:42, padding:"5px 6px", borderRadius:6, border:`1px solid ${C.line}`, background:C.panel2, color:C.text }} />
                        <button onClick={() => adminSave(m)} style={{ padding:"5px 10px", borderRadius:6, border:"none", background:C.gold, color:"#2A1F05", fontWeight:800, fontSize:12, cursor:"pointer" }}>Save</button>
                      </span>
                    ) : <span style={{ fontSize:11, color:C.mute }}>{!kickoffPassed(m, today) ? "UPCOMING" : "AWAITING RESULT"}</span>}
                </div>
              );
            })}
          </div>
        ))}
      </div>

      {user && stagedCount > 0 && tab === "predict" && (
        <div style={{ position:"fixed", left:0, right:0, bottom:0, background:"rgba(11,18,32,0.95)", borderTop:`1px solid ${C.green}`, padding:"12px 14px" }}>
          <div style={{ maxWidth:880, margin:"0 auto", display:"flex", alignItems:"center", gap:12, flexWrap:"wrap" }}>
            <span style={{ fontSize:13, flex:1 }}><b>{stagedCount}</b> pick(s) selected — one match or the whole matchday. <span style={{ color:C.gold }}>No changes after submitting.</span></span>
            <button onClick={() => setPending({})} style={{ padding:"10px 16px", borderRadius:9, border:`1px solid ${C.line}`, background:"transparent", color:C.mute, fontWeight:700, fontSize:13, cursor:"pointer" }}>Clear</button>
            <button onClick={() => setConfirming(true)} style={{ padding:"10px 22px", borderRadius:9, border:"none", background:C.green, color:"#06200F", fontWeight:800, fontSize:14, cursor:"pointer" }}>
              Lock in {stagedCount} prediction{stagedCount > 1 ? "s" : ""}
            </button>
          </div>
        </div>
      )}

      {confirming && (
        <div style={{ position:"fixed", inset:0, background:"rgba(0,0,0,0.7)", display:"flex", alignItems:"center", justifyContent:"center", padding:16, zIndex:50 }}>
          <div style={{ background:C.panel, border:`1px solid ${C.gold}`, borderRadius:16, padding:22, maxWidth:440, width:"100%", maxHeight:"80vh", overflowY:"auto" }}>
            <h3 style={{ ...display, margin:"0 0 6px", fontSize:18 }}>🔒 Final answer?</h3>
            <p style={{ fontSize:13, color:C.mute, margin:"0 0 12px" }}>These picks will be locked to <b style={{ color:C.text }}>{user?.email}</b> permanently. There is no redo.</p>
            {Object.entries(pending).filter(([, v]) => v).map(([id, v]) => {
              const m = matches.find((x) => x.id === id);
              return (
                <div key={id} style={{ fontSize:13, padding:"7px 0", borderBottom:`1px solid ${C.line}` }}>
                  {m.home.flag} {m.home.name} vs {m.away.name} {m.away.flag} → <b style={{ color:C.green }}>{v === "H" ? m.home.name : v === "A" ? m.away.name : "Draw"}</b>
                </div>
              );
            })}
            <div style={{ display:"flex", gap:8, marginTop:16 }}>
              <button onClick={() => setConfirming(false)} style={{ flex:1, padding:"11px", borderRadius:9, border:`1px solid ${C.line}`, background:"transparent", color:C.text, fontWeight:700, cursor:"pointer" }}>Go back</button>
              <button onClick={submitPicks} disabled={busy === "submit"} style={{ flex:1, padding:"11px", borderRadius:9, border:"none", background:C.green, color:"#06200F", fontWeight:800, cursor:"pointer" }}>
                {busy === "submit" ? "Locking…" : "Yes, lock them in"}
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
