/* App shell + state management for Who2Root4. */

const { useState: useAppState, useEffect: useAppEffect, useRef: useAppRef, useMemo: useAppMemo } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "light",
  "mode": "overall"
} /*EDITMODE-END*/;

function sportPathFor(sportId) {
  const s = window.SPORTS.find((sp) => sp.id === sportId);
  return "/" + (s ? s.sportPath : "baseball");
}

// Menu icons — plain stroked SVGs (matches the theme-toggle icons below)
// instead of emoji/text symbols, which render inconsistently across platforms.
const SummariesIcon = ({ size = 13 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <line x1="6" y1="20" x2="6" y2="12" />
    <line x1="12" y1="20" x2="12" y2="6" />
    <line x1="18" y1="20" x2="18" y2="14" />
  </svg>
);
const EditTeamIcon = ({ size = 13 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <path d="M12 20h9" />
    <path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z" />
  </svg>
);
const LogOutIcon = ({ size = 13 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
    <polyline points="16 17 21 12 16 7" />
    <line x1="21" y1="12" x2="9" y2="12" />
  </svg>
);

function TopNav({ tab, setTab, fav, setFav, sport, setSport, theme, setTheme, onOpenOnboarding, onOpenSummaries, user, onLogout }) {
  const [open, setOpen] = useAppState(false);
  const [userOpen, setUserOpen] = useAppState(false);
  const menuRef = useAppRef(null);
  const userMenuRef = useAppRef(null);

  useAppEffect(() => {
    const onClick = (e) => {
      if (menuRef.current && !menuRef.current.contains(e.target)) setOpen(false);
      if (userMenuRef.current && !userMenuRef.current.contains(e.target)) setUserOpen(false);
    };
    if (open || userOpen) document.addEventListener("mousedown", onClick);
    return () => document.removeEventListener("mousedown", onClick);
  }, [open, userOpen]);

  const hasTeam = !!fav;
  const t = hasTeam ? window.TEAMS[fav] : null;
  const initials = (user?.name || "?").split(" ").map((s) => s[0]).slice(0, 2).join("").toUpperCase();

  return (
    <header className="topnav">
      <div className="brand">
        <span className="brand-word">Who2Root4<sup className="w2r4-tm">TM</sup></span>
      </div>

      <div className="nav-wrap">
        <nav className="tabs">
          <button className={"tab" + (tab === "recs" ? " active" : "")} onClick={() => setTab("recs")}>
            {window.WEEK_META.periodLabel || "This Week"}
          </button>
          <button className={"tab" + (tab === "top" ? " active" : "")} onClick={() => setTab("top")}>
            Top Games
          </button>
          {hasTeam && (
            <>
              <button className={"tab" + (tab === "schedule" ? " active" : "")} onClick={() => setTab("schedule")}>
                Schedule
              </button>
              <button className={"tab" + (tab === "standings" ? " active" : "")} onClick={() => setTab("standings")}>
                Standings
              </button>
              {/* Scenarios tab hidden for now — page code kept below so it can be re-added.
              <button className={"tab" + (tab === "scenarios" ? " active" : "")} onClick={() => setTab("scenarios")}>
                Scenarios
              </button>
              */}
            </>
          )}
        </nav>
        <window.SportSwitcher variant="header" active={sport} onChange={setSport} />
      </div>

      <div className="right">
        {!hasTeam ? (
          <button className="team-chip pick-team" onClick={onOpenOnboarding}>
            <span style={{ fontSize: 14, lineHeight: 1 }}>＋</span>
            <span>Pick your team</span>
          </button>
        ) : (
        <div className="position-rel" ref={menuRef}>
          <button className="team-chip" onClick={() => setOpen(!open)} aria-label={`${t.name} — change favorite team`}>
            <span className="pill" style={{ background: t.color }}>{fav}</span>
            <span>{t.name}</span>
            <span className="caret">▾</span>
          </button>
          {open &&
          <div className="team-menu">
              <div style={{ borderBottom: "1px solid var(--border)", marginBottom: 8, paddingBottom: 6 }}>
                <button className="item" onClick={() => {setOpen(false);onOpenOnboarding();}}>
                  <span style={{ width: 14, display: "inline-grid", placeItems: "center" }}><EditTeamIcon /></span>
                  <span>Edit team &amp; rivals</span>
                </button>
              </div>
              {window.LEAGUE.conferences.flatMap((c) => window.LEAGUE.divisionOrder.map((d) => `${c} ${d}`)).map((div) => {
              const [conf, divName] = div.split(" ");
              const abbrs = (window.TEAMS_BY_DIVISION[`${conf} ${divName}`] || []).slice().sort((a, b) => {
                const ta = window.TEAMS[a], tb = window.TEAMS[b];
                const aP = ta.record[0] / Math.max(1, ta.record[0] + ta.record[1]);
                const bP = tb.record[0] / Math.max(1, tb.record[0] + tb.record[1]);
                return bP - aP || tb.record[0] - ta.record[0];
              });
              return (
                <React.Fragment key={div}>
                    <h5>{conf} {divName}</h5>
                    {abbrs.map((abbr) => {
                    const team = window.TEAMS[abbr];
                    return (
                      <button
                        key={abbr}
                        className={"item" + (abbr === fav ? " current" : "")}
                        onClick={() => {setFav(abbr);setOpen(false);}}>

                          <span className="swatch" style={{ background: team.color }}></span>
                          <span>{team.name}</span>
                          <span className="ab">{team.abbr}</span>
                        </button>);

                  })}
                  </React.Fragment>);

            })}
            </div>}
        </div>
        )}

        <div className="position-rel" ref={userMenuRef}>
          <button className="user-chip" onClick={() => setUserOpen(!userOpen)} aria-label={`${user?.name || "Account"} — account menu`}>
            <span className="avatar">{initials}</span>
            <span>{(user?.name || "Account").split(" ")[0]}</span>
            <span className="caret">▾</span>
          </button>
          {userOpen &&
          <div className="user-menu">
              <div className="who">
                <div className="name">{user?.name}</div>
                <div className="email">
                  {user?.isGuest ? "Browsing as guest" : user?.email}
                </div>
              </div>
              {user?.isGuest &&
            <button className="item" onClick={() => {setUserOpen(false);onLogout();}}
            style={{ color: "var(--accent-ink)" }}>
                  <span style={{ width: 14, display: "inline-grid", placeItems: "center" }}>＋</span>
                  Sign up to save your team
                </button>
            }
              <button className="item" onClick={() => {setUserOpen(false);onOpenSummaries();}}>
                <span style={{ width: 14, display: "inline-grid", placeItems: "center" }}><SummariesIcon /></span>
                Team Summaries
              </button>
              <button className="item" onClick={() => {setUserOpen(false);onOpenOnboarding();}}>
                <span style={{ width: 14, display: "inline-grid", placeItems: "center" }}><EditTeamIcon /></span>
                Edit team & rivals
              </button>
              <button className="item danger" onClick={() => {setUserOpen(false);onLogout();}}>
                <span style={{ width: 14, display: "inline-grid", placeItems: "center" }}><LogOutIcon /></span>
                {user?.isGuest ? "Exit guest mode" : "Log out"}
              </button>
            </div>
          }
        </div>

        <button
          className="icon-btn"
          aria-label="Toggle theme"
          onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
          title="Toggle theme">

          {theme === "dark" ?
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <circle cx="12" cy="12" r="4" />
              <path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41" />
            </svg> :

          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
            </svg>
          }
        </button>
      </div>
    </header>);

}

function App() {
  const [tw, setTweak] = window.useTweaks(TWEAK_DEFAULTS);
  // Full multi-sport prefs structure (not just this sport's slice) so a local
  // mutation — e.g. TopNav's quick favorite-change dropdown — merges into the
  // whole thing without clobbering the other sport's saved picks.
  const [teamPrefs, setTeamPrefs] = useAppState(() => window.W2R4TeamPrefs.loadTeamPrefs());
  const [detail, setDetail] = useAppState(null);
  // Sport is derived from the URL path (/football | /baseball) at load. Switching
  // sports navigates to the other path, which reloads the data layer for that
  // league (data.js reads the path on boot).
  const [sport] = useAppState(() => window.SPORT || "mlb");
  const changeSport = (s) => {
    if (s === (window.SPORT || "mlb")) return;
    window.location.assign(sportPathFor(s));
  };
  const sportPrefs = teamPrefs.bySport[sport] || { favTeam: null, dislikes: [] };
  const hasTeam = !!sportPrefs.favTeam;
  // Users without a favorite team land on the team-agnostic Top Games page.
  const [tab, setTab] = useAppState(() => (hasTeam ? "recs" : "top"));
  // Session is hydrated from localStorage on first render. Onboarding/editing
  // team prefs always happens at "/" (see HomeRoute/SportRouteGate below) —
  // by the time this component mounts under /football or /baseball, this
  // sport's prefs are guaranteed decided; only auth can still be missing
  // (e.g. a direct visit to a sport URL with no session).
  const [user, setUser] = useAppState(() => window.W2R4_Auth.loadSession());

  useAppEffect(() => {
    document.documentElement.setAttribute("data-theme", tw.theme);
    // Keep the mobile browser chrome (iOS status-bar area / Android toolbar) in
    // sync with the page background so it doesn't render white in dark mode.
    // These mirror the resolved --bg values in styles.css (light/dark).
    const THEME_BG = { light: "#fbfaf7", dark: "#0b0d11" };
    let meta = document.querySelector('meta[name="theme-color"]');
    if (!meta) {
      meta = document.createElement("meta");
      meta.setAttribute("name", "theme-color");
      document.head.appendChild(meta);
    }
    meta.setAttribute("content", THEME_BG[tw.theme] || THEME_BG.light);
  }, [tw.theme]);

  const recs = useAppMemo(
    () => window.computeRecommendations(sportPrefs.favTeam, sportPrefs.dislikes, tw.mode || "overall"),
    [sportPrefs.favTeam, sportPrefs.dislikes, tw.mode]
  );

  // Persist team prefs to localStorage whenever they change (e.g. TopNav's
  // quick favorite-change dropdown, or the team-select menu below).
  useAppEffect(() => {
    window.W2R4TeamPrefs.saveTeamPrefs(teamPrefs);
  }, [teamPrefs]);

  // If the current mode becomes unreachable (e.g., user switches team), reset to overall.
  useAppEffect(() => {
    if (!sportPrefs.favTeam) return;
    const allowed = new Set(window.availableModes(sportPrefs.favTeam));
    if (!allowed.has(tw.mode || "overall")) setTweak("mode", "overall");
  }, [sportPrefs.favTeam]);

  const setFavTeam = (abbr) => {
    setTeamPrefs((prev) => ({
      ...prev,
      bySport: { ...prev.bySport, [sport]: { favTeam: abbr, dislikes: prev.bySport[sport]?.dislikes || [] } },
    }));
  };

  // Editing team/rivals always happens on the unified selector at "/".
  const openEdit = () => { window.location.assign("/?edit=" + sport); };
  const openSummaries = () => { window.location.assign("/summary"); };

  const handleLogout = () => {
    window.W2R4_Auth.serverLogout(); // clear the cookie server-side (best-effort)
    window.W2R4_Auth.clearSession();
    setUser(null);
    setTab("recs");
  };

  if (!user) {
    return <window.Auth onAuthed={setUser} />;
  }

  return (
    <div className="app">
      <TopNav
        tab={tab}
        setTab={setTab}
        fav={sportPrefs.favTeam}
        setFav={setFavTeam}
        sport={sport}
        setSport={changeSport}
        theme={tw.theme}
        setTheme={(t) => setTweak("theme", t)}
        onOpenOnboarding={openEdit}
        onOpenSummaries={openSummaries}
        user={user}
        onLogout={handleLogout} />

      <main className="main" key={tab}>
        {tab === "recs" && (hasTeam ?
        <window.Recommendations
          recs={recs}
          fav={sportPrefs.favTeam}
          dislikes={sportPrefs.dislikes}
          onOpenDetail={setDetail}
          mode={tw.mode || "overall"}
          setMode={(m) => setTweak("mode", m)} /> :
        <div className="pick-team-cta">
          <div className="page-head">
            <div>
              <div className="eyebrow">{window.WEEK_META.label} · {window.SEASON_LABEL}</div>
              <h1>Pick your team to get a rooting guide</h1>
              <div className="sub">Choose a favorite team and we'll rank every game by how much it matters to your playoff hopes.</div>
            </div>
          </div>
          <button className="btn primary" onClick={openEdit}>Pick your team</button>
        </div>)
        }
        {tab === "top" &&
        <window.TopGames />
        }
        {hasTeam && tab === "schedule" &&
        <window.Schedule
          recs={recs}
          fav={sportPrefs.favTeam}
          onOpenDetail={setDetail}
          mode={tw.mode || "overall"}
          setMode={(m) => setTweak("mode", m)} />

        }
        {hasTeam && tab === "standings" &&
        <window.Standings fav={sportPrefs.favTeam} />
        }
        {hasTeam && tab === "scenarios" &&
        <window.Scenarios fav={sportPrefs.favTeam} />
        }
      </main>

      {detail &&
      <window.GameDetail rec={detail} fav={sportPrefs.favTeam} onClose={() => setDetail(null)} />
      }

      <footer className="w2r4-source-footer">
        Data pulled live from{" "}
        <a href={`https://site.api.espn.com/apis/site/v2/sports/${window.LEAGUE.espnSport}/scoreboard`}
        target="_blank" rel="noreferrer">
          ESPN API
        </a>
        {" · "}{window.SEASON_LABEL} · {window.WEEK_META.label}
        {window.W2R4_SOURCE?.loadedAt &&
        <> {" · "} loaded {new Date(window.W2R4_SOURCE.loadedAt).toLocaleTimeString()}</>
        }
      </footer>

      <window.TweaksPanel title="Tweaks">
        <window.TweakSection label="Display">
          <window.TweakRadio
            label="Theme"
            value={tw.theme}
            options={[
            { label: "Light", value: "light" },
            { label: "Dark", value: "dark" }]
            }
            onChange={(v) => setTweak("theme", v)} />

        </window.TweakSection>
        <window.TweakSection label="Your team">
          <window.TweakSelect
            label="Favorite team"
            value={sportPrefs.favTeam}
            options={Object.values(window.TEAMS).map((t) => ({
              label: `${t.city} ${t.name} (${t.abbr})`,
              value: t.abbr
            }))}
            onChange={setFavTeam} />

          <window.TweakSelect
            label="Goal"
            value={tw.mode || "overall"}
            options={window.MODES.map((m) => ({ label: m.label, value: m.id }))}
            onChange={(v) => setTweak("mode", v)} />

          <window.TweakButton label="Edit team & dislikes →" onClick={openEdit} />
        </window.TweakSection>
        <window.TweakSection label="Session">
          <window.TweakButton label="Log out (reset prototype)" onClick={handleLogout} />
        </window.TweakSection>
      </window.TweaksPanel>
    </div>);

}

/* ─── Bootstrap gate ──────────────────────────────────────────────────────
 * The data layer (src/data.js) fetches scoreboard JSON from
 *   github.com/JoshStremmel/Who2Root4/.cache/espn/
 * Block app render until those globals are populated so every component below
 * can rely on window.TEAMS / window.SCHEDULE / window.WEEK_META synchronously.
 */
function W2R4SportApp() {
  const [status, setStatus] = useAppState(() => window.W2R4_LOAD_STATUS?.state || "loading");
  const [errMsg, setErrMsg] = useAppState(() =>
  window.W2R4_LOAD_STATUS?.error?.message || null);

  useAppEffect(() => {
    if (status === "ready") return;
    window.W2R4_LOAD_PROMISE.
    then(() => setStatus("ready")).
    catch((e) => {setErrMsg(e?.message || String(e));setStatus("error");});
  }, []);

  if (status === "loading") {
    return (
      <div className="w2r4-boot">
        <div className="w2r4-boot-card">
          <div className="w2r4-boot-title">Who2Root4<sup className="w2r4-tm">TM</sup></div>
          <div className="w2r4-boot-sub">Pulling in the latest scores and standings…</div>
          <div className="w2r4-boot-bar"><span /></div>
        </div>
      </div>);

  }

  if (status === "error") {
    return (
      <div className="w2r4-boot">
        <div className="w2r4-boot-card error">
          <div className="w2r4-boot-title">Couldn't load the latest games</div>
          <div className="w2r4-boot-sub">
            We're having trouble reaching the live data right now. Check your
            connection and try again in a moment.
          </div>
          <button className="w2r4-boot-retry" onClick={() => location.reload()}>Retry</button>
        </div>
      </div>);

  }

  return <App />;
}

/* ─── "/" — auth, then the unified team selector or a redirect ──────────── *
 * The team selector lives here, at the site's normal URL, never nested
 * under /football or /baseball — it needs to walk every sport, so it can't
 * depend on any one sport's data being "active" via the URL. */
function HomeRoute() {
  const [user, setUser] = useAppState(() => window.W2R4_Auth.loadSession());

  if (!user) {
    return <window.Auth onAuthed={setUser} />;
  }

  const prefs = window.W2R4TeamPrefs.loadTeamPrefs();
  const params = new URLSearchParams(location.search);
  const editSport = params.get("edit");
  const startHint = params.get("start");
  const complete = window.W2R4TeamPrefs.isComplete(prefs);

  const finish = (bySport, targetSportId) => {
    const merged = { ...prefs, bySport: { ...prefs.bySport, ...bySport } };
    // Mark the local session onboarded *before* saving prefs, so the prefs
    // sync carries the updated flag up to the server (see team-prefs.js).
    if (!user.onboarded) {
      window.W2R4_Auth.saveSession({ ...user, onboarded: true });
    }
    window.W2R4TeamPrefs.saveTeamPrefs(merged);
    window.location.replace(sportPathFor(targetSportId || window.W2R4TeamPrefs.landingSport(merged)));
  };

  // Reopen for editing, or resume onboarding, whenever prefs are incomplete,
  // an explicit ?edit= is present, or this is a genuinely new user (guards
  // against stale prefs left in localStorage by a previous session/account
  // on the same browser).
  if (editSport || !complete || !user.onboarded) {
    const startSport =
    editSport ||
    (startHint && !(startHint in prefs.bySport) ? startHint : null) ||
    window.W2R4TeamPrefs.firstUndecidedSport(prefs) ||
    window.SPORTS[0].id;
    return (
      <window.Onboarding
        initialBySport={prefs.bySport}
        startSport={startSport}
        onFinish={finish} />);

  }

  // Fully onboarded, plain "/" visit → land on their sport.
  window.location.replace(sportPathFor(window.W2R4TeamPrefs.landingSport(prefs)));
  return null;
}

// /football and /baseball: redirect to "/" to resume the unified selector if
// this sport's prefs aren't decided yet (checked synchronously, before any
// data fetch starts); otherwise render the normal data-gated app.
function SportRouteGate({ sportId }) {
  const prefs = window.W2R4TeamPrefs.loadTeamPrefs();
  if (!(sportId in prefs.bySport)) {
    window.location.replace("/?start=" + sportId);
    return null;
  }
  return <W2R4SportApp />;
}

// "/summary" — auth-gated, cross-sport Team Summaries page. Doesn't depend on
// any one sport's data being "active" via the URL, so it lives outside
// SportRouteGate and fetches whichever sports the user has decided on demand
// (see src/team-summaries.jsx).
function TeamSummariesRoute() {
  const [user, setUser] = useAppState(() => window.W2R4_Auth.loadSession());
  if (!user) {
    return <window.Auth onAuthed={setUser} />;
  }
  return <window.TeamSummaries onClose={() => window.history.back()} />;
}

// Path router: /baseball runs the (prefs-gated, then data-gated) sport app;
// anything else — i.e. "/" — runs the auth + team selector flow.
// Baseball-only build: any legacy /football link is bounced to /baseball so
// there is no route into a football view.
function W2R4Bootstrap() {
  const path = (typeof location !== "undefined" ? location.pathname : "/").toLowerCase();
  if (path.startsWith("/football")) {
    window.location.replace("/baseball");
    return null;
  }
  if (path.startsWith("/baseball")) return <SportRouteGate sportId="mlb" />;
  if (path.startsWith("/summary")) return <TeamSummariesRoute />;
  return <HomeRoute />;
}

// Reconcile the session with the server (cross-device login, cookie expiry)
// before the first render, so the route gates below see the resolved auth
// state. hydrate() never throws and falls back to the local cache when the
// backend is unavailable, so the app still renders if the API is down.
(async function boot() {
  try { await window.W2R4_Auth.hydrate(); } catch (_) { /* ignore */ }
  ReactDOM.createRoot(document.getElementById("root")).render(<W2R4Bootstrap />);
})();
