const { useState, useEffect, useRef } = React;

// ============================================================
// Nav menu definitions
// ============================================================
const NAV = [
  { id: "analytics", label: "Analytics" },
  { id: "roster",    label: "Roster", subs: [
    { id: "sit",     label: "Start / Sit" },
    { id: "waiver",  label: "Waiver" },
    { id: "opt",     label: "Lineup Optimizer" },
  ]},
  { id: "games",     label: "Games" },
  { id: "draft",     label: "Draft", subs: [
    { id: "board",    label: "Draft Board" },
    { id: "rankings", label: "Rankings (Pre-Season)" },
    { id: "live",     label: "Draft Live" },
  ]},
  { id: "metrics",   label: "Metrics",    subs: [
    { id: "weekly",    label: "Weekly Points" },
    { id: "standings", label: "Standings" },
    { id: "position",  label: "Position Metrics" },
  ]},
  { id: "statistics", label: "Statistics", subs: [
    { id: "performance", label: "Performance" },
    { id: "trends",      label: "Player Trends" },
  ]},
  { id: "projections", label: "Projections", subs: [
    { id: "tape",     label: "Player Tape" },
    { id: "rankings", label: "Player Breakdown" },
  ]},
];

// ============================================================
// Top navigation
// ============================================================
function TopNav({
  current, sub, onNavigate, collapsed, setCollapsed,
  session, profile, leagues, activeLeagueId, onLeagueSelect,
  onLoginClick, onLogout, onSettingsClick, onBack, canGoBack
}) {
  const [openDrop, setOpenDrop] = useState(null);
  const [showSeasonPassFlyout, setShowSeasonPassFlyout] = useState(false);
  const dropRef = useRef(null);

  useEffect(() => {
    function onDoc(e) {
      if (dropRef.current && !dropRef.current.contains(e.target)) {
        setOpenDrop(null);
        setShowSeasonPassFlyout(false);
      }
    }
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, []);

  return (
    <header style={{
      position: "sticky", top: 0, zIndex: 40,
      background: "rgba(5,8,7,0.92)",
      backdropFilter: "blur(14px)",
      borderBottom: "1px solid var(--green-600)",
    }}>
      <div style={{
        maxWidth: 1440, margin: "0 auto",
        padding: "12px 28px",
        display: "flex", alignItems: "center", justifyContent: "space-between", gap: 20,
      }}>
        {/* Brand + collapse toggle */}
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          {canGoBack && (
            <button
              onClick={onBack}
              title="Back"
              aria-label="Back"
              style={{
                display: "flex", alignItems: "center", justifyContent: "center",
                width: 32, height: 32, flex: "0 0 auto",
                background: "transparent", border: "1px solid var(--green-600)", borderRadius: 8,
                color: "var(--mint-soft)", cursor: "pointer",
              }}
            >
              <span style={{ transform: "rotate(180deg)", display: "inline-flex" }}><window.IconChevron size={14} /></span>
            </button>
          )}
          <button onClick={() => onNavigate("landing")} style={{
            display: "flex", alignItems: "center", gap: 10,
            background: "transparent", border: "none", cursor: "pointer", padding: 0
          }}>
            <div style={{
              width: 40, height: 40, borderRadius: 10,
              background: "var(--mint)",
              display: "flex", alignItems: "center", justifyContent: "center",
              fontFamily: "Space Grotesk", fontWeight: 700, fontSize: 15, color: "var(--black)",
              letterSpacing: "-0.04em",
              boxShadow: "0 10px 28px rgba(149,249,174,0.18)"
            }}>949</div>
            {!collapsed && (
              <div style={{ textAlign: "left" }}>
                <div className="display" style={{ fontSize: 15, color: "var(--mint-soft)", fontWeight: 700, lineHeight: 1 }}>949Fantasy</div>
                <div style={{ fontSize: 10, color: "var(--slate)", marginTop: 3, letterSpacing: "0.04em" }}>Fantasy intelligence platform</div>
              </div>
            )}
          </button>

          <button
            onClick={() => setCollapsed(c => !c)}
            title={collapsed ? "Expand nav" : "Collapse nav"}
            style={{
              display: "flex", alignItems: "center", justifyContent: "center",
              width: 24, height: 24, marginLeft: 4,
              background: "transparent", border: "1px solid var(--green-600)", borderRadius: 6,
              color: "var(--slate)", cursor: "pointer"
            }}>
            <span style={{ transform: collapsed ? "rotate(0deg)" : "rotate(180deg)", display: "inline-flex" }}>
              <window.IconChevron size={12} />
            </span>
          </button>
        </div>

        {/* Center nav (hidden when collapsed) */}
        {!collapsed && (
          <nav ref={dropRef} style={{ display: "flex", gap: 4, alignItems: "center" }}>
            {NAV.map(item => {
              const active = current === item.id;
              const hasSub = !!item.subs;
              const isOpen = openDrop === item.id;
              return (
                <div key={item.id} style={{ position: "relative" }}>
                  <button
                    onClick={() => {
                      if (hasSub) {
                        setOpenDrop(isOpen ? null : item.id);
                      } else {
                        onNavigate(item.id);
                        setOpenDrop(null);
                      }
                    }}
                    style={{
                      padding: "8px 14px", borderRadius: 8, border: "none",
                      background: active ? "rgba(149,249,174,0.08)" : "transparent",
                      color: active ? "var(--mint)" : "var(--slate)",
                      fontSize: 13, fontWeight: 500, fontFamily: "Sora",
                      cursor: "pointer", transition: "all 0.12s",
                      display: "inline-flex", alignItems: "center", gap: 5,
                    }}
                    onMouseEnter={e => { if (!active) e.currentTarget.style.color = "var(--mint-soft)"; }}
                    onMouseLeave={e => { if (!active) e.currentTarget.style.color = "var(--slate)"; }}>
                    {item.label}
                    {hasSub && <span style={{ transform: isOpen ? "rotate(90deg)" : "rotate(0deg)", display: "inline-flex", transition: "transform 0.15s" }}><window.IconChevron size={10} /></span>}
                  </button>

                  {hasSub && isOpen && (
                    <div style={{
                      position: "absolute", top: "calc(100% + 6px)", left: 0,
                      minWidth: 200, padding: 6,
                      background: "var(--green-900)",
                      border: "1px solid var(--green-600)",
                      borderRadius: 10,
                      boxShadow: "0 20px 50px rgba(0,0,0,0.4)",
                      zIndex: 50,
                      animation: "fadeIn 0.15s ease both"
                    }}>
                      {item.subs.map(s => {
                        const activeSub = active && sub === s.id;
                        return (
                          <button key={s.id} onClick={() => { onNavigate(item.id, s.id); setOpenDrop(null); }} style={{
                            display: "block", width: "100%", textAlign: "left",
                            padding: "9px 12px", borderRadius: 6, border: "none",
                            background: activeSub ? "rgba(149,249,174,0.1)" : "transparent",
                            color: activeSub ? "var(--mint)" : "var(--mint-soft)",
                            fontSize: 12, fontFamily: "Sora", cursor: "pointer", transition: "background 0.1s"
                          }}
                            onMouseEnter={e => { if (!activeSub) e.currentTarget.style.background = "rgba(149,249,174,0.04)"; }}
                            onMouseLeave={e => { if (!activeSub) e.currentTarget.style.background = "transparent"; }}>
                            {s.label}
                          </button>
                        );
                      })}
                    </div>
                  )}
                </div>
              );
            })}
          </nav>
        )}

        {/* Right side */}
        <div style={{ display: "flex", alignItems: "center", gap: 10, position: "relative" }}>
          {session && (
            <select
              aria-label="Select league"
              value={activeLeagueId || ""}
              onChange={e => onLeagueSelect(e.target.value)}
              style={{
                height: 34, minWidth: 180, maxWidth: 260,
                borderRadius: 8, border: "1px solid var(--green-600)",
                background: "var(--green-900)", color: "var(--mint-soft)",
                fontFamily: "Sora", fontSize: 12, fontWeight: 600,
                padding: "0 10px", outline: "none"
              }}
            >
              {!activeLeagueId && <option value="" disabled>Select or add league</option>}
              {leagues.map(league => <option key={league.id} value={league.id}>{league.name}</option>)}
              <option value="add">+ Add League</option>
            </select>
          )}
          <button title="Notifications" style={{
            background: "transparent", border: "1px solid var(--green-600)",
            borderRadius: 8, padding: 8, cursor: "pointer", color: "var(--slate)",
            display: "flex", alignItems: "center", justifyContent: "center",
            position: "relative"
          }}>
            <window.IconBell size={15} />
            <span style={{ position: "absolute", top: 5, right: 5, width: 6, height: 6, borderRadius: "50%", background: "var(--mint)" }} />
          </button>
          <button title="Settings" onClick={onSettingsClick} style={{
            background: "transparent", border: "1px solid var(--green-600)",
            borderRadius: 8, padding: 8, cursor: "pointer", color: "var(--slate)",
            display: "flex", alignItems: "center", justifyContent: "center",
          }}>
            <window.IconSettings size={15} />
          </button>
          {!session && (
            <>
              <button
                className="btn"
                onClick={() => setShowSeasonPassFlyout(current => !current)}
                style={{ padding: "8px 14px", fontSize: 12 }}
              >
                Season Pass
              </button>
              {showSeasonPassFlyout && (
                <div style={{
                  position: "absolute",
                  top: "calc(100% + 8px)",
                  right: 92,
                  minWidth: 220,
                  padding: 12,
                  borderRadius: 10,
                  background: "rgba(5,8,7,0.98)",
                  border: "1px solid var(--green-600)",
                  boxShadow: "0 20px 50px rgba(0,0,0,0.4)",
                  zIndex: 60,
                }}>
                  <div className="mono" style={{ color: "var(--mint)", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase" }}>Season Pass</div>
                  <div style={{ color: "var(--mint-soft)", fontSize: 14, fontWeight: 700, marginTop: 8 }}>CURRENTLY IN BETA!</div>
                  <div style={{ color: "var(--slate)", fontSize: 12, lineHeight: 1.45, marginTop: 6 }}>
                    Access is invite-only while we finish live rankings, projections, and draft workflows.
                  </div>
                </div>
              )}
            </>
          )}
          {session ? (
            <button className="btn ghost" onClick={onLogout} style={{ padding: "8px 14px", fontSize: 12 }}>
              Log Out
            </button>
          ) : (
            <button className="btn" onClick={onLoginClick} style={{ padding: "8px 14px", fontSize: 12 }}>
              Log In
            </button>
          )}
        </div>
      </div>
    </header>
  );
}

const TEAM_COUNT_OPTIONS = [6, 8, 10, 12, 14];
const ROSTER_SIZE_OPTIONS = Array.from({ length: 9 }, (_, index) => index + 10);

function createLocalLeague(index = 1) {
  return {
    id: `local-${Date.now()}-${index}`,
    name: `League ${index}`,
    teamName: "My Team",
    teamCount: 12,
    scoring: "ppr",
    draftPosition: 1,
    rosterSize: 16,
    teams: Array.from({ length: 12 }, (_, idx) => ({
      slot: idx + 1,
      name: idx === 0 ? "My Team" : `Team ${idx + 1}`,
      isUserTeam: idx === 0,
    })),
    picks: [],
  };
}

function buildLeagueTeams(teamCount, draftPosition, teamName, existingTeams = []) {
  return Array.from({ length: teamCount }, (_, idx) => {
    const slot = idx + 1;
    const existing = existingTeams.find(team => team.slot === slot);
    const isUserTeam = slot === Number(draftPosition);
    return {
      slot,
      name: isUserTeam ? (teamName || existing?.name || "My Team") : (existing?.name || `Team ${slot}`),
      isUserTeam,
    };
  });
}

function leagueCacheKey(userId) {
  return `949.leagues.v1.${userId}`;
}

function restoreCachedLeagues(userId) {
  try {
    const parsed = JSON.parse(window.localStorage.getItem(leagueCacheKey(userId)) || "null");
    if (!parsed || !Array.isArray(parsed.leagues) || !parsed.leagues.length) return null;
    return parsed;
  } catch {
    return null;
  }
}

function saveCachedLeagues(userId, leagues, activeLeagueId) {
  if (!userId || !Array.isArray(leagues)) return;
  try {
    window.localStorage.setItem(leagueCacheKey(userId), JSON.stringify({
      savedAt: Date.now(),
      activeLeagueId: activeLeagueId || "",
      leagues,
    }));
  } catch (error) {
    console.warn("League cache skipped", error);
  }
}

function formatLeagueRoundPick(pickNumber, teamCount = 12, roundNumber, roundSlot) {
  if (pickNumber > 0 && typeof window.formatRoundPick === "function") {
    return window.formatRoundPick(pickNumber - 1, teamCount);
  }
  const round = Number(roundNumber) || Math.max(1, Math.ceil(pickNumber / Math.max(1, teamCount)));
  const slot = Number(roundSlot) || ((pickNumber - 1) % Math.max(1, teamCount)) + 1;
  return `${round}.${String(slot).padStart(2, "0")}`;
}

function persistPickRow(leagueId, pick, teamCount = 12) {
  const pickNumber = Number(pick.pick) || 0;
  const roundPickRaw = pick.roundPick;
  const roundPick = typeof roundPickRaw === "string"
    ? (Number(String(roundPickRaw).split(".")[1]) || Number(String(roundPickRaw).split(".")[0]) || pickNumber)
    : Number(roundPickRaw || pickNumber);
  return {
    league_id: leagueId,
    pick_number: pickNumber,
    round_number: Number(pick.roundNumber) || Math.max(1, Math.ceil(pickNumber / Math.max(1, teamCount))),
    round_pick: Number.isFinite(roundPick) ? Math.trunc(roundPick) : pickNumber,
    team_slot: Number(pick.teamSlot) || 1,
    team_name: pick.teamName || `Team ${pick.teamSlot || 1}`,
    player_id: pick.playerId || null,
    player_name: pick.playerName || "Unknown",
    player_position: pick.playerPosition || null,
    player_team: pick.playerTeam || null,
  };
}

function AuthModal({ onClose, onLogin }) {
  const [identity, setIdentity] = useState("");
  const [password, setPassword] = useState("");
  const [error, setError] = useState("");

  async function submit(e) {
    e.preventDefault();
    setError("");
    const result = await onLogin(identity, password);
    if (!result.ok) setError(result.error || "Login failed");
  }

  return (
    <Modal title="Log In" onClose={onClose}>
      <form onSubmit={submit} style={{ display: "grid", gap: 12 }}>
        <Field label="Email" value={identity} onChange={setIdentity} autoFocus />
        <Field label="Password" value={password} onChange={setPassword} type="password" />
        {error && <div style={{ color: "var(--red)", fontSize: 12 }}>{error}</div>}
        <button className="btn" type="submit">Log In</button>
      </form>
    </Modal>
  );
}

function SettingsModal({ profile, onClose, onSave }) {
  const [draft, setDraft] = useState(profile);
  const [password, setPassword] = useState("");
  const [status, setStatus] = useState("");

  async function submit(e) {
    e.preventDefault();
    setStatus("Saving...");
    const result = await onSave(draft, password);
    setStatus(result.ok ? "Saved" : result.error || "Save failed");
  }

  return (
    <Modal title="Settings" onClose={onClose}>
      <form onSubmit={submit} style={{ display: "grid", gap: 12 }}>
        <Field label="First Name" value={draft.firstName || ""} onChange={value => setDraft({ ...draft, firstName: value })} />
        <Field label="Last Name" value={draft.lastName || ""} onChange={value => setDraft({ ...draft, lastName: value })} />
        <Field label="Username" value={draft.username || ""} onChange={value => setDraft({ ...draft, username: value })} />
        <Field label="Email" value={draft.email || ""} onChange={value => setDraft({ ...draft, email: value })} />
        <Field label="New Password" value={password} onChange={setPassword} type="password" placeholder="Leave blank to keep current password" />
        {status && <div style={{ color: status === "Saved" ? "var(--mint)" : "var(--slate)", fontSize: 12 }}>{status}</div>}
        <button className="btn" type="submit">Save</button>
      </form>
    </Modal>
  );
}

function SetPasswordModal({ profile, onSave, onCancel }) {
  const [draft, setDraft] = useState(profile);
  const [password, setPassword] = useState("");
  const [confirm, setConfirm] = useState("");
  const [status, setStatus] = useState("");

  async function submit(e) {
    e.preventDefault();
    if (!draft.firstName?.trim() || !draft.lastName?.trim() || !draft.username?.trim() || !draft.email?.trim()) {
      setStatus("First name, last name, username, and email are required.");
      return;
    }
    if (password.length < 8) {
      setStatus("Password must be at least 8 characters.");
      return;
    }
    if (password !== confirm) {
      setStatus("Passwords do not match.");
      return;
    }
    setStatus("Saving...");
    const result = await onSave(draft, password);
    setStatus(result.ok ? "Password saved" : result.error || "Password update failed");
  }

  return (
    <Modal title="Set Password" onClose={onCancel} closeLabel="Sign Out">
      <form onSubmit={submit} style={{ display: "grid", gap: 12 }}>
        <p style={{ margin: 0, color: "var(--slate)", fontSize: 13, lineHeight: 1.5 }}>
          Create your password to finish the invite setup.
        </p>
        <Field label="First Name" value={draft.firstName || ""} onChange={value => setDraft({ ...draft, firstName: value })} autoFocus />
        <Field label="Last Name" value={draft.lastName || ""} onChange={value => setDraft({ ...draft, lastName: value })} />
        <Field label="Username" value={draft.username || ""} onChange={value => setDraft({ ...draft, username: value })} />
        <Field label="Email" value={draft.email || ""} onChange={value => setDraft({ ...draft, email: value })} type="email" />
        <Field label="Password" value={password} onChange={setPassword} type="password" />
        <Field label="Confirm Password" value={confirm} onChange={setConfirm} type="password" />
        {status && <div style={{ color: status === "Password saved" ? "var(--mint)" : "var(--slate)", fontSize: 12 }}>{status}</div>}
        <button className="btn" type="submit">Save Password</button>
      </form>
    </Modal>
  );
}

function LeagueModal({ onClose, onCreate }) {
  const [league, setLeague] = useState({ ...createLocalLeague(1), name: "" });
  const [status, setStatus] = useState("");
  const [creating, setCreating] = useState(false);

  async function submit(e) {
    e.preventDefault();
    const name = league.name.trim();
    if (!name) {
      setStatus("League name is required.");
      return;
    }
    setCreating(true);
    setStatus("Creating league...");
    const result = await onCreate({ ...league, name });
    if (!result?.ok) {
      setStatus(result?.error || "League creation failed.");
      setCreating(false);
    }
  }

  return (
    <Modal title="Add League" onClose={onClose}>
      <form onSubmit={submit} style={{ display: "grid", gap: 12 }}>
        <Field label="League Name" value={league.name} onChange={value => setLeague({ ...league, name: value })} placeholder="e.g. Sunday League" autoFocus />
        <Field label="Team Name" value={league.teamName} onChange={value => setLeague({ ...league, teamName: value })} />
        <SelectField label="Teams" value={league.teamCount} onChange={value => setLeague({ ...league, teamCount: Number(value), draftPosition: Math.min(league.draftPosition, Number(value)) })} options={TEAM_COUNT_OPTIONS.map(value => ({ value, label: String(value) }))} />
        <SelectField label="Scoring" value={league.scoring} onChange={value => setLeague({ ...league, scoring: value })} options={[
          { value: "standard", label: "Standard" },
          { value: "half", label: "Half-PPR" },
          { value: "ppr", label: "PPR" },
        ]} />
        <SelectField label="Draft Position" value={league.draftPosition} onChange={value => setLeague({ ...league, draftPosition: Number(value) })} options={Array.from({ length: league.teamCount }, (_, index) => ({ value: index + 1, label: String(index + 1) }))} />
        <SelectField label="Roster Size" value={league.rosterSize} onChange={value => setLeague({ ...league, rosterSize: Number(value) })} options={ROSTER_SIZE_OPTIONS.map(value => ({ value, label: String(value) }))} />
        {status && <div style={{ color: status === "Creating league..." ? "var(--slate)" : "var(--red)", fontSize: 12 }}>{status}</div>}
        <button className="btn" type="submit" disabled={creating}>{creating ? "Creating..." : "Create League"}</button>
      </form>
    </Modal>
  );
}

function Modal({ title, children, onClose, closeLabel = "Close" }) {
  return (
    <div style={{
      position: "fixed", inset: 0, zIndex: 100,
      background: "rgba(0,0,0,0.64)",
      display: "flex", alignItems: "center", justifyContent: "center",
      padding: 20
    }}>
      <section className="card" style={{ width: "min(460px, 100%)", padding: 20, background: "var(--green-900)" }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12, marginBottom: 16 }}>
          <h2 className="display" style={{ margin: 0, fontSize: 22 }}>{title}</h2>
          <button className="btn ghost" onClick={onClose} style={{ padding: "7px 10px" }}>{closeLabel}</button>
        </div>
        {children}
      </section>
    </div>
  );
}

function NavigationFallback({ onHome }) {
  return (
    <div className="view-enter" style={{ maxWidth: 720, margin: "0 auto", padding: "64px 24px" }}>
      <div className="card" style={{ padding: 28 }}>
        <div className="mono" style={{ color: "var(--gold)", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase" }}>Navigation recovery</div>
        <h1 className="display" style={{ margin: "10px 0 8px", color: "var(--mint-soft)", fontSize: 28 }}>This screen is unavailable</h1>
        <p style={{ margin: 0, color: "var(--slate)", lineHeight: 1.6 }}>
          The requested page did not load. Return to the dashboard and continue without refreshing the app.
        </p>
        <button className="btn" onClick={onHome} style={{ marginTop: 18 }}>Return to Analytics</button>
      </div>
    </div>
  );
}

function Field({ label, value, onChange, type = "text", placeholder = "", autoFocus = false }) {
  return (
    <label style={{ display: "grid", gap: 6, color: "var(--slate)", fontSize: 12, fontWeight: 700 }}>
      {label}
      <input
        autoFocus={autoFocus}
        type={type}
        value={value}
        placeholder={placeholder}
        onChange={e => onChange(e.target.value)}
        style={{
          height: 38, borderRadius: 8, border: "1px solid var(--green-600)",
          background: "rgba(5,8,7,0.78)", color: "var(--mint-soft)",
          padding: "0 10px", outline: "none", fontFamily: "Sora"
        }}
      />
    </label>
  );
}

function SelectField({ label, value, onChange, options }) {
  return (
    <label style={{ display: "grid", gap: 6, color: "var(--slate)", fontSize: 12, fontWeight: 700 }}>
      {label}
      <select
        value={value}
        onChange={e => onChange(e.target.value)}
        style={{
          height: 38, borderRadius: 8, border: "1px solid var(--green-600)",
          background: "rgba(5,8,7,0.78)", color: "var(--mint-soft)",
          padding: "0 10px", outline: "none", fontFamily: "Sora"
        }}
      >
        {options.map(option => <option key={option.value} value={option.value}>{option.label}</option>)}
      </select>
    </label>
  );
}

class ViewErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { error: null };
  }
  static getDerivedStateFromError(error) {
    return { error };
  }
  componentDidCatch(error) {
    console.error("View crashed", error);
  }
  componentDidUpdate(prevProps) {
    if (this.props.resetKey !== prevProps.resetKey && this.state.error) {
      this.setState({ error: null });
    }
  }
  render() {
    if (this.state.error) {
      return (
        <div style={{ maxWidth: 720, margin: "0 auto", padding: "48px 24px" }}>
          <div className="display" style={{ fontSize: 28, color: "var(--mint-soft)" }}>This screen failed to load</div>
          <p style={{ color: "var(--slate)", lineHeight: 1.55 }}>{String(this.state.error.message || this.state.error)}</p>
          <button className="btn" type="button" onClick={() => this.setState({ error: null })}>Retry</button>
        </div>
      );
    }
    return this.props.children;
  }
}

// ============================================================
// App
// ============================================================
function App() {
  const [view, setView] = useState("landing");
  const [sub, setSub] = useState(null);
  const [selected, setSelected] = useState(null);
  const [collapsed, setCollapsed] = useState(false);
  const [supabase, setSupabase] = useState(null);
  const [session, setSession] = useState(null);
  const [profile, setProfile] = useState({ email: "", username: "", firstName: "", lastName: "" });
  const [leagues, setLeagues] = useState([]);
  const [activeLeagueId, setActiveLeagueId] = useState("");
  const [showLogin, setShowLogin] = useState(false);
  const [showSettings, setShowSettings] = useState(false);
  const [showLeagueModal, setShowLeagueModal] = useState(false);
  const [needsPasswordSetup, setNeedsPasswordSetup] = useState(false);
  const skipRemoteLeagueReloadUntil = useRef(0);

  const activeLeague = React.useMemo(
    () => leagues.find(league => league.id === activeLeagueId) || null,
    [leagues, activeLeagueId],
  );

  useEffect(() => {
    if (!session || typeof window.buildLiveLeagueContext !== "function" || typeof window.publishLiveLeagueContext !== "function") return;
    if (!activeLeague) return;
    try {
      window.publishLiveLeagueContext(window.buildLiveLeagueContext(activeLeague));
    } catch (error) {
      console.warn("Live league publish failed", error);
    }
  }, [
    session?.user?.id,
    activeLeague?.id,
    activeLeague?.picks?.length,
    activeLeague?.draftPosition,
    activeLeague?.teamName,
    activeLeague?.teams?.length,
  ]);

  useEffect(() => {
    if (!session?.user?.id || !leagues.length) return;
    saveCachedLeagues(session.user.id, leagues, activeLeagueId);
  }, [session?.user?.id, leagues, activeLeagueId]);

  function historyHost() {
    try {
      return window.parent && window.parent !== window ? window.parent : window;
    } catch {
      return window;
    }
  }

  function pushNavigationState(nextView, nextSub = null, playerId = null) {
    const host = historyHost();
    const state = { nine49App: true, view: nextView, sub: nextSub, playerId };
    const url = new URL(host.location.href);
    const params = new URLSearchParams();
    params.set("view", nextView);
    if (nextSub) params.set("sub", nextSub);
    if (playerId) params.set("player", playerId);
    url.hash = params.toString();
    host.history.pushState(state, "", url);
  }

  function canonicalizeNav(v, s = null) {
    if (v === "lineup") return { view: "roster", sub: "sit" };
    if (v === "projections" && s === "lineup-opt") return { view: "roster", sub: "opt" };
    if (v === "roster" && !s) return { view: "roster", sub: "sit" };
    if (v === "draft" && !s) return { view: "draft", sub: "board" };
    return { view: v, sub: s };
  }

  function navigate(v, s = null) {
    const next = canonicalizeNav(v, s);
    if (view !== next.view || sub !== next.sub) pushNavigationState(next.view, next.sub);
    setView(next.view);
    setSub(next.sub);
    setSelected(null);
    window.scrollTo({ top: 0, behavior: "smooth" });
  }

  function selectPlayer(p) {
    const resolved = (window.resolveCanonicalPlayer && window.resolveCanonicalPlayer(p)) || p;
    if (!resolved) return;
    pushNavigationState("player", null, resolved.id);
    setSelected(resolved);
    setView("player");
    setSub(null);
    window.scrollTo({ top: 0, behavior: "smooth" });
  }

  function findPlayerById(playerId) {
    if (!playerId) return null;
    const pool = [...(window.DRAFT_PLAYERS || []), ...(window.PLAYERS || [])];
    const hit = pool.find((item) => item.id === playerId);
    if (hit) return window.resolveCanonicalPlayer ? window.resolveCanonicalPlayer(hit) : hit;
    if (window.findPlayerByName) {
      const byName = window.findPlayerByName(String(playerId).replace(/-/g, " "));
      if (byName) return window.resolveCanonicalPlayer ? window.resolveCanonicalPlayer(byName) : byName;
    }
    return window.resolveCanonicalPlayer ? window.resolveCanonicalPlayer({ id: playerId, name: playerId, pos: "FLEX", team: "FA", proj: 0 }) : null;
  }

  function goBack() {
    const host = historyHost();
    if (host.history.state?.nine49App) {
      host.history.back();
      return;
    }
    navigate("analytics");
  }

  useEffect(() => {
    const host = historyHost();
    function applyHistoryState(event) {
      const state = event.state;
      if (!state?.nine49App) {
        setSelected(null);
        setView("landing");
        setSub(null);
        return;
      }
      if (state.view === "player") {
        const player = findPlayerById(state.playerId);
        if (!player) {
          setSelected(null);
          setView("projections");
          setSub("rankings");
          return;
        }
        setSelected(player);
      } else {
        setSelected(null);
      }
      const canonical = canonicalizeNav(state.view || "landing", state.sub || null);
      setView(canonical.view);
      setSub(canonical.sub);
      window.scrollTo(0, 0);
    }
    host.addEventListener("popstate", applyHistoryState);
    if (host.history.state?.nine49App) {
      applyHistoryState({ state: host.history.state });
    } else {
      const params = new URLSearchParams((host.location.hash || "").replace(/^#/, ""));
      const initialView = params.get("view");
      if (initialView) {
        const initialState = {
          nine49App: true,
          view: initialView,
          sub: params.get("sub"),
          playerId: params.get("player"),
        };
        host.history.replaceState(initialState, "", host.location.href);
        applyHistoryState({ state: initialState });
      }
    }
    return () => host.removeEventListener("popstate", applyHistoryState);
  }, []);

  // Expose for programmatic / export navigation
  useEffect(() => {
    window.__goToView = (v, s = null) => {
      if (v === "player") {
        const chase = (window.PLAYERS || []).find(p => p.id === "jchase") || (window.DRAFT_PLAYERS || [])[0];
        if (chase) selectPlayer(chase);
      } else {
        navigate(v, s);
      }
    };
  }, [view, sub]);

  const didEnterApp = useRef(false);
  useEffect(() => {
    if (!session) {
      didEnterApp.current = false;
      return;
    }
    if (didEnterApp.current) return;
    didEnterApp.current = true;
    if (view === "landing") navigate("analytics");
  }, [session]);

  useEffect(() => {
    if (typeof window.hydrateDemoDataFromApi === "function") {
      window.hydrateDemoDataFromApi();
    } else if (typeof window.hydrateNflTeamsFromApi === "function") {
      window.hydrateNflTeamsFromApi();
    }
  }, []);

  useEffect(() => {
    let active = true;
    async function bootAuth() {
      try {
        const config = await fetch("/api/client-config", { cache: "no-store" }).then(r => r.json());
        if (!config.supabaseUrl || !config.supabaseAnonKey || !window.supabase?.createClient) return;
        const client = window.supabase.createClient(config.supabaseUrl, config.supabaseAnonKey);
        if (!active) return;
        setSupabase(client);
        const ownHash = window.location.hash || "";
        const parentHash = window.parent && window.parent !== window ? (window.parent.location.hash || "") : "";
        const authHash = ownHash || parentHash;
        const params = new URLSearchParams(authHash.replace(/^#/, ""));
        const inviteType = params.get("type");
        const { data } = await client.auth.getSession();
        if (data?.session) {
          await applySession(client, data.session);
          if (inviteType === "invite" || inviteType === "recovery") setNeedsPasswordSetup(true);
          if (authHash.includes("access_token")) {
            window.history.replaceState(null, "", window.location.pathname + window.location.search);
            if (window.parent && window.parent !== window) {
              window.parent.history.replaceState(null, "", window.parent.location.pathname + window.parent.location.search);
            }
          }
        }
        client.auth.onAuthStateChange((event, nextSession) => {
          if (event === "PASSWORD_RECOVERY") {
            setNeedsPasswordSetup(true);
          }
          if (nextSession) applySession(client, nextSession);
          else {
            setSession(null);
            setProfile({ email: "", username: "", firstName: "", lastName: "" });
            setLeagues([]);
            setActiveLeagueId("");
          }
        });
      } catch (error) {
        console.warn("Supabase auth boot failed", error);
      }
    }
    bootAuth();
    return () => { active = false; };
  }, []);

  async function applySession(client, nextSession) {
    setSession(nextSession);
    const user = nextSession.user;
    const cached = restoreCachedLeagues(user.id);
    if (cached?.leagues?.length) {
      setLeagues(cached.leagues);
      if (cached.activeLeagueId) setActiveLeagueId(cached.activeLeagueId);
    }
    const meta = user.user_metadata || {};
    const nextProfile = {
      email: user.email || "",
      username: meta.username || "",
      firstName: meta.first_name || "",
      lastName: meta.last_name || "",
    };

    try {
      const { data: profileRow } = await client.from("profiles").select("*").eq("id", user.id).maybeSingle();
      if (profileRow) {
        nextProfile.email = profileRow.email || nextProfile.email;
        nextProfile.username = profileRow.username || nextProfile.username;
        nextProfile.firstName = profileRow.first_name || nextProfile.firstName;
        nextProfile.lastName = profileRow.last_name || nextProfile.lastName;
      }
    } catch (error) {
      console.warn("Profile load failed", error);
    }

    setProfile(nextProfile);
    try {
      await client.from("profiles").upsert({
        id: user.id,
        email: nextProfile.email,
        username: nextProfile.username || null,
        first_name: nextProfile.firstName || null,
        last_name: nextProfile.lastName || null,
        updated_at: new Date().toISOString(),
      });
    } catch (error) {
      console.warn("Profile ensure failed", error);
    }
    await loadLeagues(client, user.id);
  }

  async function loadLeagues(client, userId, preferId = "") {
    try {
      const { data: nested, error: nestedError } = await client
        .from("beta_leagues")
        .select("*, beta_league_teams(*), beta_draft_picks(*)")
        .eq("owner_id", userId)
        .order("created_at");
      if (nestedError) console.warn("Nested league load failed", nestedError);

      const { data: leagueOnly, error: leagueError } = await client
        .from("beta_leagues")
        .select("*")
        .eq("owner_id", userId)
        .order("created_at");
      if (leagueError) throw leagueError;

      const leagueRows = (nested && nested.length && !nestedError) ? nested : (leagueOnly || []);
      let teamRows = [];
      let pickRows = [];
      const ids = leagueRows.map((row) => row.id);
      if (ids.length) {
        const [teamsRes, picksRes] = await Promise.all([
          client.from("beta_league_teams").select("*").in("league_id", ids).order("slot"),
          client.from("beta_draft_picks").select("*").in("league_id", ids).order("pick_number").range(0, 4999),
        ]);
        if (teamsRes.error) console.warn("League teams load failed", teamsRes.error);
        if (picksRes.error) console.warn("Draft picks load failed", picksRes.error);
        teamRows = teamsRes.data || [];
        pickRows = picksRes.data || [];
      }

      const rows = (leagueRows || []).map((row) => {
        const embeddedTeams = row.beta_league_teams;
        const embeddedPicks = row.beta_draft_picks;
        const teamsSource = teamRows.filter((team) => team.league_id === row.id).length
          ? teamRows.filter((team) => team.league_id === row.id)
          : (Array.isArray(embeddedTeams) ? embeddedTeams : []);
        const teams = teamsSource
          .slice()
          .sort((a, b) => a.slot - b.slot)
          .map((team) => ({
            slot: team.slot,
            name: team.name,
            isUserTeam: !!team.is_user_team,
          }));
        const fromQuery = pickRows.filter((pick) => pick.league_id === row.id);
        const embeddedForLeague = (Array.isArray(embeddedPicks) ? embeddedPicks : [])
          .filter((pick) => !pick.league_id || pick.league_id === row.id);
        const rawPicks = fromQuery.length ? fromQuery : embeddedForLeague;
        const picks = rawPicks
          .slice()
          .sort((a, b) => a.pick_number - b.pick_number)
          .map((pick) => ({
            pick: pick.pick_number,
            roundNumber: pick.round_number,
            roundPick: formatLeagueRoundPick(pick.pick_number, row.team_count || 12, pick.round_number, pick.round_pick),
            teamSlot: pick.team_slot,
            teamName: pick.team_name,
            playerId: pick.player_id,
            playerName: pick.player_name,
            playerPosition: pick.player_position,
            playerTeam: pick.player_team,
          }));
        const flagged = teams.filter((team) => team.isUserTeam);
        const inferredSlot = flagged.length === 1
          ? Number(flagged[0].slot)
          : (Number(row.draft_position) || Number(flagged[0]?.slot) || 1);
        const alignedTeams = (teams.length ? teams : buildLeagueTeams(row.team_count, inferredSlot, flagged[0]?.name || "My Team"))
          .map((team) => ({
            ...team,
            isUserTeam: Number(team.slot) === Number(inferredSlot),
          }));
        const userTeam = alignedTeams.find((team) => team.isUserTeam);
        return {
          id: row.id,
          ownerId: row.owner_id,
          name: row.name,
          teamName: userTeam?.name || "My Team",
          teamCount: row.team_count,
          scoring: row.scoring,
          draftPosition: inferredSlot,
          rosterSize: row.roster_size,
          draftStatus: row.draft_status || (picks.length ? "live" : "setup"),
          teams: alignedTeams,
          picks,
        };
      });
      setLeagues(rows);
      setActiveLeagueId((current) => {
        let stored = "";
        try { stored = window.localStorage.getItem("949.activeLeagueId") || ""; } catch { stored = ""; }
        if (preferId && rows.some((row) => row.id === preferId)) {
          try { window.localStorage.setItem("949.activeLeagueId", preferId); } catch { /* ignore */ }
          return preferId;
        }
        if (current && rows.some((row) => row.id === current)) return current;
        if (stored && rows.some((row) => row.id === stored)) return stored;
        return rows[rows.length - 1]?.id || "";
      });
    } catch (error) {
      console.warn("League load failed", error);
    }
  }

  const loadLeaguesRef = useRef(loadLeagues);
  loadLeaguesRef.current = loadLeagues;
  const activeLeagueIdRef = useRef(activeLeagueId);
  activeLeagueIdRef.current = activeLeagueId;

  useEffect(() => {
    if (!supabase || !session?.user?.id) return;
    const userId = session.user.id;
    let timer = null;
    const reload = () => {
      if (Date.now() < skipRemoteLeagueReloadUntil.current) return;
      clearTimeout(timer);
      timer = setTimeout(() => {
        if (Date.now() < skipRemoteLeagueReloadUntil.current) return;
        loadLeaguesRef.current(supabase, userId, activeLeagueIdRef.current);
      }, 400);
    };
    const channel = supabase
      .channel(`league-live:${userId}`)
      .on("postgres_changes", { event: "*", schema: "public", table: "beta_leagues", filter: `owner_id=eq.${userId}` }, reload)
      .on("postgres_changes", { event: "*", schema: "public", table: "beta_league_teams" }, reload)
      .on("postgres_changes", { event: "*", schema: "public", table: "beta_draft_picks" }, reload)
      .subscribe((status) => {
        if (status === "CHANNEL_ERROR" || status === "TIMED_OUT") {
          console.warn("League realtime subscribe failed", status);
        }
      });
    return () => {
      clearTimeout(timer);
      supabase.removeChannel(channel);
    };
  }, [supabase, session?.user?.id]);

  async function login(identity, password) {
    if (!supabase) return { ok: false, error: "Supabase client is not configured" };
    const email = identity.includes("@") ? identity.trim() : `${identity.trim()}@949fantasy.com`;
    const { data, error } = await supabase.auth.signInWithPassword({ email, password });
    if (error) return { ok: false, error: error.message };
    if (data.session) await applySession(supabase, data.session);
    setShowLogin(false);
    return { ok: true };
  }

  async function logout() {
    if (supabase) await supabase.auth.signOut();
    setSession(null);
    setLeagues([]);
    setActiveLeagueId("");
    if (typeof window.publishLiveLeagueContext === "function") {
      window.publishLiveLeagueContext(null);
    } else if (typeof window.restoreDemoGlobals === "function") {
      window.restoreDemoGlobals();
    }
  }

  async function saveSettings(nextProfile, password) {
    if (!supabase || !session) return { ok: false, error: "Not signed in" };
    const normalizedProfile = {
      email: (nextProfile.email || "").trim().toLowerCase(),
      username: (nextProfile.username || "").trim(),
      firstName: (nextProfile.firstName || "").trim(),
      lastName: (nextProfile.lastName || "").trim(),
    };
    if (!normalizedProfile.email || !normalizedProfile.username || !normalizedProfile.firstName || !normalizedProfile.lastName) {
      return { ok: false, error: "First name, last name, username, and email are required" };
    }
    const authUpdate = {};
    if (normalizedProfile.email && normalizedProfile.email !== session.user.email) authUpdate.email = normalizedProfile.email;
    if (password) authUpdate.password = password;
    authUpdate.data = {
      username: normalizedProfile.username,
      first_name: normalizedProfile.firstName,
      last_name: normalizedProfile.lastName,
    };
    const { error: authError } = await supabase.auth.updateUser(authUpdate);
    if (authError) return { ok: false, error: authError.message };
    const { error: profileError } = await supabase.from("profiles").upsert({
      id: session.user.id,
      email: normalizedProfile.email,
      username: normalizedProfile.username,
      first_name: normalizedProfile.firstName,
      last_name: normalizedProfile.lastName,
      updated_at: new Date().toISOString(),
    });
    if (profileError) return { ok: false, error: profileError.message };
    setProfile(normalizedProfile);
    return { ok: true };
  }

  async function saveInvitePassword(nextProfile, password) {
    const result = await saveSettings(nextProfile, password);
    if (!result.ok) return result;
    setNeedsPasswordSetup(false);
    return { ok: true };
  }

  async function createLeague(league) {
    if (!session || !supabase) {
      setShowLogin(true);
      return { ok: false, error: "Log in before adding a league." };
    }
    const id = crypto.randomUUID();
    const teams = buildLeagueTeams(league.teamCount, league.draftPosition, league.teamName);
    const { error } = await supabase.from("beta_leagues").insert({
      id,
      owner_id: session.user.id,
      name: league.name,
      team_count: league.teamCount,
      scoring: league.scoring,
      draft_position: league.draftPosition,
      roster_size: league.rosterSize,
      draft_status: "setup",
    });
    if (error) {
      return { ok: false, error: error.message };
    }
    const { error: teamsError } = await supabase.from("beta_league_teams").insert(
      teams.map(team => ({
        league_id: id,
        slot: team.slot,
        name: team.name,
        is_user_team: team.isUserTeam,
      })),
    );
    if (teamsError) {
      await supabase.from("beta_leagues").delete().eq("id", id);
      return { ok: false, error: teamsError.message };
    }
    setLeagues(current => [...current, { ...league, id, ownerId: session.user.id, teams, picks: [] }]);
    setActiveLeagueId(id);
    try { window.localStorage.setItem("949.activeLeagueId", id); } catch { /* ignore */ }
    setShowLeagueModal(false);
    navigate("draft", "live");
    return { ok: true };
  }

  async function updateLeagueDraftState(nextLeague) {
    if (!supabase || !session) return;
    const teams = buildLeagueTeams(nextLeague.teamCount, nextLeague.draftPosition, nextLeague.teamName, nextLeague.teams || []);
    const { error: leagueError } = await supabase.from("beta_leagues").upsert({
      id: nextLeague.id,
      owner_id: session.user.id,
      name: nextLeague.name,
      team_count: nextLeague.teamCount,
      scoring: nextLeague.scoring,
      draft_position: nextLeague.draftPosition,
      roster_size: nextLeague.rosterSize,
      draft_status: (nextLeague.picks?.length || nextLeague.draftStatus === "complete")
        ? (nextLeague.draftStatus === "complete" ? "complete" : "live")
        : (nextLeague.draftStatus || "setup"),
      updated_at: new Date().toISOString(),
    });
    if (leagueError) {
      console.warn("League update failed", leagueError);
      return;
    }
    const { error: teamError } = await supabase.from("beta_league_teams").upsert(
      teams.map(team => ({
        league_id: nextLeague.id,
        slot: team.slot,
        name: team.name,
        is_user_team: team.isUserTeam,
        updated_at: new Date().toISOString(),
      })),
      { onConflict: "league_id,slot" }
    );
    if (teamError) {
      console.warn("League team update failed", teamError);
      return;
    }
    setLeagues(current => current.map(league => league.id === nextLeague.id
      ? { ...nextLeague, teams, picks: nextLeague.picks || league.picks || [] }
      : league));
  }

  async function saveLeaguePick(leagueId, pick) {
    if (!supabase || !session || !leagueId) return;
    skipRemoteLeagueReloadUntil.current = Date.now() + 12000;
    const target = leagues.find((league) => league.id === leagueId);
    const { error } = await supabase.from("beta_draft_picks").upsert(
      persistPickRow(leagueId, pick, target?.teamCount || 12),
      { onConflict: "league_id,pick_number" }
    );
    if (error) {
      console.warn("Pick save failed", error);
      return;
    }
    if (target?.draftStatus !== "live" && target?.draftStatus !== "complete") {
      await supabase.from("beta_leagues").update({
        draft_status: "live",
        updated_at: new Date().toISOString(),
      }).eq("id", leagueId);
    }
    setLeagues(current => current.map(league => {
      if (league.id !== leagueId) return league;
      const picks = [...(league.picks || []).filter(existing => existing.pick !== pick.pick), pick]
        .sort((a, b) => a.pick - b.pick);
      return { ...league, picks, draftStatus: league.draftStatus === "complete" ? "complete" : "live" };
    }));
  }

  async function finishLeagueDraft(leagueId, picks = [], meta = {}) {
    if (!supabase || !session || !leagueId) return { ok: false, error: "Not signed in" };
    const target = leagues.find((league) => league.id === leagueId) || activeLeague;
    const teamCount = target?.teamCount || 12;
    const teamName = meta.teamName || target?.teamName || "My Team";
    const inferredSlot = Number(meta.draftPosition) > 0
      ? Number(meta.draftPosition)
      : (window.resolveUserSlot || window.inferUserSlot || ((league) => league?.draftPosition || 1))({
        ...target,
        picks,
        teamName,
        teams: meta.teams || target?.teams,
        draftPosition: target?.draftPosition,
      });
    const rows = (picks || []).map((pick) => persistPickRow(leagueId, pick, teamCount)).filter((row) => row.pick_number > 0);
    for (let i = 0; i < rows.length; i += 40) {
      const chunk = rows.slice(i, i + 40);
      const { error } = await supabase.from("beta_draft_picks").upsert(chunk, { onConflict: "league_id,pick_number" });
      if (error) {
        console.warn("Draft finish write failed", error);
        return { ok: false, error: error.message };
      }
    }
    const teams = buildLeagueTeams(teamCount, inferredSlot, teamName, meta.teams || target?.teams || []);
    await supabase.from("beta_leagues").update({
      draft_status: "complete",
      draft_position: inferredSlot,
      updated_at: new Date().toISOString(),
    }).eq("id", leagueId);
    await supabase.from("beta_league_teams").upsert(
      teams.map((team) => ({
        league_id: leagueId,
        slot: team.slot,
        name: team.name,
        is_user_team: team.isUserTeam,
        updated_at: new Date().toISOString(),
      })),
      { onConflict: "league_id,slot" }
    );
    const sortedPicks = [...picks].sort((a, b) => a.pick - b.pick);
    setLeagues((current) => current.map((league) => (
      league.id === leagueId
        ? { ...league, picks: sortedPicks, draftStatus: "complete", draftPosition: inferredSlot, teams, teamName }
        : league
    )));
    setActiveLeagueId(leagueId);
    try { window.localStorage.setItem("949.activeLeagueId", leagueId); } catch { /* ignore */ }
    await loadLeagues(supabase, session.user.id, leagueId);
    setLeagues((current) => current.map((league) => (
      league.id === leagueId && sortedPicks.length && (league.picks?.length || 0) < sortedPicks.length
        ? { ...league, picks: sortedPicks, draftStatus: "complete", draftPosition: inferredSlot, teams, teamName }
        : league
    )));
    return { ok: true };
  }

  async function resetLeaguePicks(leagueId) {
    if (!supabase || !session || !leagueId) return;
    const { error } = await supabase.from("beta_draft_picks").delete().eq("league_id", leagueId);
    if (error) {
      console.warn("Draft reset failed", error);
      return;
    }
    setLeagues(current => current.map(league => league.id === leagueId ? { ...league, picks: [] } : league));
  }

  async function swapWaiverPlayer(leagueId, dropPlayer, addPlayer) {
    if (!supabase || !session || !leagueId || !dropPlayer || !addPlayer) {
      return { ok: false, error: "Missing roster swap" };
    }
    const league = leagues.find((row) => row.id === leagueId);
    const userSlot = (window.resolveUserSlot || window.inferUserSlot)
      ? (window.resolveUserSlot || window.inferUserSlot)(league)
      : ((league?.teams || []).find((team) => team.isUserTeam)?.slot || league?.draftPosition || 1);
    const dropPick = (league?.picks || []).find((pick) => (
      Number(pick.teamSlot) === Number(userSlot)
      && (pick.playerId === dropPlayer.id || pick.playerName === dropPlayer.name)
    ));
    if (!dropPick) return { ok: false, error: "Could not find that roster player" };
    const nextPick = {
      ...dropPick,
      playerId: addPlayer.id,
      playerName: addPlayer.name,
      playerPosition: addPlayer.pos,
      playerTeam: addPlayer.team,
    };
    await saveLeaguePick(leagueId, nextPick);
    return { ok: true };
  }

  function selectLeague(value) {
    if (value === "add") {
      setShowLeagueModal(true);
      return;
    }
    setActiveLeagueId(value);
    try { window.localStorage.setItem("949.activeLeagueId", value); } catch { /* ignore */ }
  }

  function requestLeagueSetup() {
    if (!session) {
      setShowLogin(true);
      return;
    }
    setShowLeagueModal(true);
  }

  // Smart current/sub mapping for nav highlight
  const navCurrent = view === "player" ? "projections" :
                     view === "rankings" ? "projections" :
                     view === "lineup" ? "roster" :
                     view;

  const metricsTab = view === "metrics" && ["weekly", "standings", "position"].includes(sub) ? sub : "weekly";
  const statsTab   = view === "statistics" && ["performance", "trends"].includes(sub) ? sub : "performance";
  const rosterTab  = view === "roster" && ["sit", "waiver", "opt"].includes(sub) ? sub : "sit";

  const liveLeague = session ? activeLeague : null;

  return (
    <div style={{ minHeight: "100vh", background: "var(--black)", color: "var(--mint-soft)" }}>
      <TopNav
        current={navCurrent}
        sub={sub}
        onNavigate={navigate}
        collapsed={collapsed}
        setCollapsed={setCollapsed}
        session={session}
        profile={profile}
        leagues={leagues}
        activeLeagueId={activeLeagueId}
        onLeagueSelect={selectLeague}
        onLoginClick={() => setShowLogin(true)}
        onLogout={logout}
        onSettingsClick={() => session ? setShowSettings(true) : setShowLogin(true)}
        onBack={goBack}
        canGoBack={view !== "landing"}
      />
      <main>
        <ViewErrorBoundary resetKey={`${view}:${sub || ""}`}>
        {view === "landing"     && <div data-screen-label="01 Landing">      <LandingView    onNavigate={navigate} onSelectPlayer={selectPlayer} /></div>}
        {view === "analytics"    && <div data-screen-label="02 Analytics">     <SnapshotView   onNavigate={navigate} onSelectPlayer={selectPlayer} activeLeague={liveLeague} session={!!session} /></div>}
        {view === "metrics"     && <div data-screen-label="03 Metrics">      <MetricsView    tab={metricsTab} setTab={(t) => navigate("metrics", t)} onSelectPlayer={selectPlayer} activeLeague={liveLeague} /></div>}
        {view === "statistics"  && <div data-screen-label="04 Statistics">   <StatisticsView tab={statsTab}    setTab={(t) => navigate("statistics", t)} onSelectPlayer={selectPlayer} activeLeague={liveLeague} session={!!session} /></div>}
        {(view === "roster" && rosterTab === "sit") || view === "lineup" ? (
          <div data-screen-label="05 Start Sit"><LineupView onSelectPlayer={selectPlayer} activeLeague={liveLeague} session={!!session} /></div>
        ) : null}
        {view === "roster" && rosterTab === "waiver" && (
          <div data-screen-label="05 Waiver">
            <WaiverView
              onSelectPlayer={selectPlayer}
              activeLeague={liveLeague}
              session={!!session}
              onSwapWaiver={swapWaiverPlayer}
            />
          </div>
        )}
        {view === "roster" && rosterTab === "opt" && (
          <div data-screen-label="05 Lineup Optimizer"><LineupView onSelectPlayer={selectPlayer} activeLeague={liveLeague} session={!!session} /></div>
        )}
        {view === "games"       && <div data-screen-label="05 Games">        <GamesView      onSelectPlayer={selectPlayer} activeLeague={liveLeague} session={!!session} /></div>}
        {view === "draft" && sub === "rankings" && <div data-screen-label="06 Draft Rankings"><DraftRankingsView onSelectPlayer={selectPlayer} /></div>}
        {view === "draft" && sub === "live" && <div data-screen-label="06 Draft Live"><DraftView key={activeLeague?.id || "no-league"} manualLive onSelectPlayer={selectPlayer} activeLeague={activeLeague} onRequestLeague={requestLeagueSetup} onLeagueChange={updateLeagueDraftState} onFinishDraft={finishLeagueDraft} onResetPicks={resetLeaguePicks} onSavePick={saveLeaguePick} /></div>}
        {view === "draft" && sub !== "rankings" && sub !== "live" && <div data-screen-label="06 Draft Board"><DraftView onSelectPlayer={selectPlayer} /></div>}
        {view === "projections" && sub === "tape" && <div data-screen-label="06 Projections Tape"><PlayerTapeView onSelectPlayer={selectPlayer} /></div>}
        {view === "projections" && sub !== "tape" && <div data-screen-label="06 Projections">  <RankingsView   onSelectPlayer={selectPlayer} /></div>}
        {view === "rankings"    && <div data-screen-label="06 Projections">  <RankingsView   onSelectPlayer={selectPlayer} /></div>}
        {view === "player"      && <div data-screen-label="07 Player">       <PlayerDetailView player={selected} onBack={goBack} /></div>}
        {!["landing", "analytics", "metrics", "statistics", "roster", "lineup", "games", "draft", "projections", "rankings", "player"].includes(view) && <NavigationFallback onHome={() => navigate("analytics")} />}
        </ViewErrorBoundary>
      </main>

      {showLogin && <AuthModal onClose={() => setShowLogin(false)} onLogin={login} />}
      {showSettings && <SettingsModal profile={profile} onClose={() => setShowSettings(false)} onSave={saveSettings} />}
      {showLeagueModal && <LeagueModal onClose={() => setShowLeagueModal(false)} onCreate={createLeague} />}
      {needsPasswordSetup && <SetPasswordModal profile={profile} onSave={saveInvitePassword} onCancel={logout} />}

      <Footer onNavigate={navigate} />
    </div>
  );
}

function Footer({ onNavigate }) {
  return (
    <footer style={{ borderTop: "1px solid var(--green-600)", marginTop: 24, padding: "32px 0" }}>
      <div style={{
        maxWidth: 1440, margin: "0 auto", padding: "0 32px",
        display: "grid", gridTemplateColumns: "1.5fr 1fr 1fr 1fr", gap: 24, alignItems: "flex-start"
      }}>
        <div>
          <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
            <div style={{
              width: 32, height: 32, borderRadius: 8, background: "var(--mint)",
              display: "flex", alignItems: "center", justifyContent: "center",
              fontFamily: "Space Grotesk", fontWeight: 700, fontSize: 13, color: "var(--black)", letterSpacing: "-0.04em"
            }}>949</div>
            <span className="display" style={{ fontSize: 15, color: "var(--mint-soft)" }}>949Fantasy</span>
          </div>
          <div style={{ marginTop: 14, fontSize: 12, color: "var(--slate)", maxWidth: 320, lineHeight: 1.5 }}>
            Premium fantasy football intelligence. Built by data engineers, used by managers who treat their team like a portfolio.
          </div>
          <div className="mono" style={{ marginTop: 18, fontSize: 10, color: "var(--slate-dim)", letterSpacing: "0.06em" }}>
            © 2026 · 949 Labs · Made for the long playoff push
          </div>
        </div>
        {[
          { title: "Product",   items: [
            { l: "Analytics",   n: "analytics"  },
            { l: "Metrics",     n: "metrics"    },
            { l: "Statistics",  n: "statistics" },
            { l: "Start / Sit", n: "roster", s: "sit" },
            { l: "Waiver",      n: "roster", s: "waiver" },
            { l: "Games",       n: "games"      },
            { l: "Draft",       n: "draft", s: "board" },
            { l: "Projections", n: "projections"},
          ]},
          { title: "Resources", items: [{ l: "Methodology", n: "draft", s: "rankings" }, { l: "Player Metrics", n: "metrics", s: "position" }, { l: "Player Tape", n: "projections", s: "tape" }] },
          { title: "Company",   items: [{ l: "About", n: "landing" }, { l: "Pricing", href: "/season-pass" }] },
        ].map(col => (
          <div key={col.title}>
            <div className="mono" style={{ fontSize: 10, color: "var(--mint)", letterSpacing: "0.14em", textTransform: "uppercase", marginBottom: 14 }}>{col.title}</div>
            <ul style={{ listStyle: "none", padding: 0, margin: 0, display: "flex", flexDirection: "column", gap: 8 }}>
              {col.items.map(item => (
                <li key={item.l}>
                  <a href={item.href || "#"} onClick={e => { if (item.n && onNavigate) { e.preventDefault(); onNavigate(item.n, item.s || null); } }}
                     style={{ fontSize: 13, color: "var(--slate)", textDecoration: "none", cursor: "pointer" }}>{item.l}</a>
                </li>
              ))}
            </ul>
          </div>
        ))}
      </div>
    </footer>
  );
}

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