// =============================================================================
// ROOT APP — wires it all together with React Router (updated)
// =============================================================================

import { useState, useEffect, useMemo, useRef, useCallback } from 'react';
import {
  BrowserRouter, Routes, Route, Navigate, Outlet,
  useNavigate, useLocation, useParams, useSearchParams, useOutletContext,
} from 'react-router-dom';

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": "daylight",
  "density": "cozy",
  "confettiOnLead": true,
  "showRulebookEverywhere": false
}/*EDITMODE-END*/;

const PALETTE_MAP = {
  daylight:    ["#b21e2e", "#d4a847", "#f7f4ec"],
  crimsonGold: ["#b21e2e", "#d4a847", "#0f0a0b"],
  midnight:    ["#ef4444", "#fbbf24", "#08101c"],
  onyx:        ["#a21d2c", "#c8a96a", "#0c0c0d"],
};
const PALETTE_LABELS = {
  daylight:    "Daylight",
  crimsonGold: "Crimson Gold",
  midnight:    "Midnight Court",
  onyx:        "Onyx Champagne",
};

const API_BASE = import.meta.env.VITE_API_URL || "http://localhost:8000";

// Map a pathname to the legacy "screen" id used by AppShell for highlighting
function screenFromPath(pathname) {
  const seg = pathname.split("/").filter(Boolean)[0] || "dashboard";
  if (seg === "teams") {
    const parts = pathname.split("/").filter(Boolean);
    return parts[2] === "members" ? "member" : "team";
  }
  return seg;
}

// ---------------------------------------------------------------------------
// Auth context (shared up the tree without a provider lib)
// ---------------------------------------------------------------------------
function useAuth() {
  const [loggedIn, setLoggedIn] = useState(false);
  const [authChecking, setAuthChecking] = useState(true);
  const [authUser, setAuthUser] = useState(() => {
    try { return JSON.parse(localStorage.getItem("authUser") || "null"); } catch { return null; }
  });

  useEffect(() => {
    const token = localStorage.getItem("authToken");
    if (!token) { setAuthChecking(false); return; }
    fetch(`${API_BASE}/api/me`, {
      headers: { Accept: "application/json", Authorization: `Bearer ${token}` },
    })
      .then(res => res.ok ? res.json() : Promise.reject())
      .then(data => {
        if (data.user) {
          localStorage.setItem("authUser", JSON.stringify(data.user));
          setAuthUser(data.user);
        }
        setLoggedIn(true);
      })
      .catch(() => {
        localStorage.removeItem("authToken");
        localStorage.removeItem("authUser");
      })
      .finally(() => setAuthChecking(false));
  }, []);

  const logout = useCallback(async () => {
    const token = localStorage.getItem("authToken");
    if (token) {
      try {
        await fetch(`${API_BASE}/api/logout`, {
          method: "POST",
          headers: { Accept: "application/json", Authorization: `Bearer ${token}` },
        });
      } catch {}
    }
    localStorage.removeItem("authToken");
    localStorage.removeItem("authUser");
    setAuthUser(null);
    setLoggedIn(false);
  }, []);

  const refreshUser = useCallback(() => {
    try { setAuthUser(JSON.parse(localStorage.getItem("authUser") || "null")); } catch {}
    setLoggedIn(true);
  }, []);

  return { loggedIn, authChecking, authUser, logout, refreshUser };
}

// ---------------------------------------------------------------------------
// Active week helpers (synced to ?week= query param)
// ---------------------------------------------------------------------------
function useActiveWeek() {
  const [searchParams, setSearchParams] = useSearchParams();
  const unlocked = RVL_WEEKS.filter(w => rvlIsWeekUnlocked(w.id));
  const latest = (unlocked[unlocked.length - 1] || RVL_WEEKS[0]).id;
  const stored = searchParams.get("week");
  const isCumulative = searchParams.get("cumulative") === "1";
  // If stored week is missing, locked, or older than latest unlocked, use latest
  const week = (stored && rvlIsWeekUnlocked(stored)) ? stored : latest;

  // Sync URL when computed week differs from what's stored (skip on cumulative view)
  useEffect(() => {
    if (!isCumulative && week !== stored) {
      setSearchParams(prev => {
        const sp = new URLSearchParams(prev);
        sp.set("week", week);
        return sp;
      }, { replace: true });
    }
  }, [week, stored, isCumulative, setSearchParams]);

  const setWeek = useCallback((next) => {
    setSearchParams(prev => {
      const sp = new URLSearchParams(prev);
      sp.set("week", next);
      return sp;
    }, { replace: true });
  }, [setSearchParams]);
  return [week, setWeek];
}

function useActiveView(defaultValue = "week") {
  const [searchParams, setSearchParams] = useSearchParams();
  const view = searchParams.get("view") || defaultValue;
  const setView = useCallback((next) => {
    setSearchParams(prev => {
      const sp = new URLSearchParams(prev);
      sp.set("view", next);
      return sp;
    }, { replace: true });
  }, [setSearchParams]);
  return [view, setView];
}

// ---------------------------------------------------------------------------
// Protected layout — auth + shell + outlet
// ---------------------------------------------------------------------------
function ProtectedLayout({ auth, scoresRev, bumpScores, tweaks, setTweak, confettiTrigger, setConfettiTrigger, setLogoutConfirm }) {
  const navigate = useNavigate();
  const location = useLocation();
  const [activeWeek, setActiveWeek] = useActiveWeek();

  const paletteClass = tweaks.palette === "daylight" ? "" : `palette-${tweaks.palette}`;
  const activeScreen = screenFromPath(location.pathname);

  useEffect(() => {
    if (!tweaks.confettiOnLead) return;
    if (activeScreen === "leaderboard") {
      const t = setTimeout(() => setConfettiTrigger(c => c + 1), 350);
      return () => clearTimeout(t);
    }
  }, [activeScreen, tweaks.confettiOnLead, setConfettiTrigger]);

  const handleNav = (id) => navigate(`/${id}` + (activeWeek ? `?week=${activeWeek}` : ""));

  return (
    <div className={paletteClass}>
      <Confetti trigger={confettiTrigger}/>
      <AppShell
        activeScreen={activeScreen}
        onNav={handleNav}
        activeWeek={activeWeek}
        onWeekChange={setActiveWeek}
        onLogout={() => setLogoutConfirm(true)}
        palette={tweaks.palette}
        user={auth.authUser}
      >
        <Outlet context={{ activeWeek, setActiveWeek, scoresRev, bumpScores }}/>
      </AppShell>

      <TweaksPanel title="Tweaks">
        <TweakSection title="Palette" description="Theme the entire scoreboard.">
          <div className="twk-row">
            <div className="twk-lbl"><span>Theme</span></div>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 8, width: "100%" }}>
              {Object.entries(PALETTE_MAP).map(([id, colors]) => {
                const active = tweaks.palette === id;
                return (
                  <button key={id} onClick={() => setTweak("palette", id)} style={{
                    display: "flex", alignItems: "center", gap: 8,
                    padding: "8px 10px",
                    background: active ? "var(--twk-active-bg, rgba(255,255,255,.06))" : "transparent",
                    border: `1px solid ${active ? "var(--twk-active-border, var(--gold))" : "var(--twk-border, rgba(255,255,255,.12))"}`,
                    borderRadius: 8, cursor: "pointer",
                    color: "var(--twk-fg, #fff)", textAlign: "left",
                  }}>
                    <span style={{
                      display: "inline-flex", borderRadius: 6, overflow: "hidden",
                      boxShadow: "0 0 0 1px rgba(0,0,0,.3)",
                    }}>
                      {colors.map((c, i) => (
                        <span key={i} style={{ width: 14, height: 22, background: c, display: "block" }}/>
                      ))}
                    </span>
                    <span style={{ fontSize: 12, fontWeight: 600 }}>{PALETTE_LABELS[id]}</span>
                  </button>
                );
              })}
            </div>
          </div>
        </TweakSection>
        <TweakSection title="Behavior">
          <TweakToggle
            label="Confetti when leaderboard loads"
            value={tweaks.confettiOnLead}
            onChange={v => setTweak("confettiOnLead", v)}
          />
          <TweakButton label="🎉 Fire confetti now" onClick={() => setConfettiTrigger(c => c + 1)}/>
        </TweakSection>
        <TweakSection title="Data">
          <TweakButton label="Reset all scores to mock data" onClick={() => {
            rvlResetToMock();
            bumpScores();
          }}/>
          <TweakButton label="Sign out (back to login)" onClick={() => setLogoutConfirm(true)}/>
        </TweakSection>
      </TweaksPanel>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Page wrappers — adapt existing components to route params
// ---------------------------------------------------------------------------
function DashboardPage() {
  const { activeWeek, scoresRev } = useOutletContext();
  const navigate = useNavigate();
  return <Dashboard key={`dash-${activeWeek}-${scoresRev}`} activeWeek={activeWeek} onNav={(id, filter, scope) => { const isCum = scope === "all"; const weekParam = isCum ? activeWeek : (scope || activeWeek); const p = new URLSearchParams(); p.set("week", weekParam); if (filter) p.set("filter", filter); if (isCum) p.set("cumulative", "1"); const url = `/${id}?${p.toString()}`; console.log("NAV url=", url, "scope=", scope, "activeWeek=", activeWeek); navigate(url); }}/>;
}

function EntryPage() {
  const { activeWeek, scoresRev, bumpScores } = useOutletContext();
  const { search } = useLocation();
  const [searchParams, setSearchParams] = useSearchParams();
  const params = new URLSearchParams(search);
  const initFilter = params.get("filter") || null;
  const isCumulative = params.get("cumulative") === "1";
  const initScope = isCumulative ? "all" : null;

  useEffect(() => {
    if (isCumulative && searchParams.get("week")) {
      setSearchParams(prev => { const sp = new URLSearchParams(prev); sp.delete("week"); return sp; }, { replace: true });
    }
  }, [isCumulative, searchParams, setSearchParams]);

  return <WeeklyEntry key={`entry-${activeWeek}-${scoresRev}-${initFilter}-${initScope}`} activeWeek={activeWeek} onSaved={bumpScores} initFilter={initFilter} initScope={initScope}/>;
}

function LeaderboardPage() {
  const { activeWeek, scoresRev } = useOutletContext();
  const [view, setView] = useActiveView("week");
  const navigate = useNavigate();
  return (
    <LiveLeaderboard
      key={`lb-${scoresRev}`}
      activeWeek={activeWeek}
      view={view}
      onViewChange={setView}
      onTeamClick={(id) => navigate(`/teams/${encodeURIComponent(id)}?week=${activeWeek}`)}
    />
  );
}

function MembersPage() {
  const { activeWeek, scoresRev } = useOutletContext();
  const [view, setView] = useActiveView("week");
  const navigate = useNavigate();
  if (!rvlIsWeekUnlocked(activeWeek)) return <WeekLocked weekId={activeWeek}/>;
  return (
    <MemberLeaderboard
      key={`ml-${scoresRev}`}
      activeWeek={activeWeek}
      view={view}
      onViewChange={setView}
      onMemberClick={(tid, member) =>
        navigate(`/teams/${encodeURIComponent(tid)}/members/${encodeURIComponent(member)}?week=${activeWeek}`, { state: { from: "members" } })
      }
    />
  );
}

function ManagePage() {
  const { bumpScores } = useOutletContext();
  return <ManageTeams onChange={bumpScores}/>;
}

function MastersPage() {
  const { bumpScores } = useOutletContext();
  return <MastersScreen onChange={bumpScores}/>;
}

function H2HPage() {
  const { activeWeek, scoresRev } = useOutletContext();
  if (!rvlIsWeekUnlocked(activeWeek)) return <WeekLocked weekId={activeWeek}/>;
  return <HeadToHead key={`h2h-${scoresRev}`} activeWeek={activeWeek}/>;
}

function HistoryPage() {
  const { activeWeek, scoresRev } = useOutletContext();
  if (!rvlIsWeekUnlocked(activeWeek)) return <WeekLocked weekId={activeWeek}/>;
  return <History key={`hist-${scoresRev}`} activeWeek={activeWeek}/>;
}

function RecapPage() {
  const { activeWeek, scoresRev } = useOutletContext();
  return <WeeklyRecap key={`recap-${scoresRev}`} activeWeek={activeWeek}/>;
}

function TeamPage() {
  const { activeWeek, scoresRev } = useOutletContext();
  const { teamId } = useParams();
  const navigate = useNavigate();
  if (!rvlIsWeekUnlocked(activeWeek)) return <WeekLocked weekId={activeWeek}/>;
  return (
    <TeamDetail
      key={`team-${teamId}-${scoresRev}`}
      teamId={teamId}
      activeWeek={activeWeek}
      onBack={() => navigate(`/leaderboard?week=${activeWeek}`)}
      onMemberClick={(tid, member) =>
        navigate(`/teams/${encodeURIComponent(tid)}/members/${encodeURIComponent(member)}?week=${activeWeek}`)
      }
    />
  );
}

function MemberPage() {
  const { activeWeek, scoresRev } = useOutletContext();
  const { teamId, memberName } = useParams();
  const navigate = useNavigate();
  const location = useLocation();
  const fromMembers = location.state?.from === "members";
  if (!rvlIsWeekUnlocked(activeWeek)) return <WeekLocked weekId={activeWeek}/>;
  return (
    <MemberScorecard
      key={`mem-${memberName}-${scoresRev}`}
      teamId={teamId}
      member={memberName}
      activeWeek={activeWeek}
      onBack={() => fromMembers
        ? navigate(`/members?week=${activeWeek}`)
        : navigate(`/teams/${encodeURIComponent(teamId)}?week=${activeWeek}`)
      }
    />
  );
}

// ---------------------------------------------------------------------------
// Login route
// ---------------------------------------------------------------------------
function LoginRoute({ auth }) {
  const navigate = useNavigate();
  const location = useLocation();
  const rawFrom = location.state?.from || "/dashboard";
  const from = rawFrom === "/" || rawFrom.startsWith("/?") ? `/dashboard${rawFrom.slice(1)}` : rawFrom;

  if (auth.loggedIn) {
    return <Navigate to={from} replace/>;
  }
  return (
    <Login onLogin={() => {
      auth.refreshUser();
      navigate(from, { replace: true });
    }}/>
  );
}

// ---------------------------------------------------------------------------
// Auth guard
// ---------------------------------------------------------------------------
function RequireAuth({ auth, children }) {
  const location = useLocation();
  if (!auth.loggedIn) {
    return <Navigate to="/login" state={{ from: location.pathname + location.search }} replace/>;
  }
  return children;
}

// ---------------------------------------------------------------------------
// App root
// ---------------------------------------------------------------------------
function App() {
  const auth = useAuth();
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [scoresRev, setScoresRev] = useState(0);
  const bumpScores = useCallback(() => setScoresRev(r => r + 1), []);
  const [confettiTrigger, setConfettiTrigger] = useState(0);
  const [logoutConfirm, setLogoutConfirm] = useState(false);

  useEffect(() => {
    rvlLoadPersistedState();
    bumpScores();
  }, [bumpScores]);

  const paletteClass = tweaks.palette === "daylight" ? "" : `palette-${tweaks.palette}`;

  if (auth.authChecking) {
    return null; // global loader stays visible
  }

  return (
    <BrowserRouter>
      <ToastHost/>
      <ConfirmHost/>
      <Routes>
        <Route path="/login" element={<LoginRoute auth={auth}/>}/>
        <Route
          element={
            <RequireAuth auth={auth}>
              <ProtectedLayout
                auth={auth}
                scoresRev={scoresRev}
                bumpScores={bumpScores}
                tweaks={tweaks}
                setTweak={setTweak}
                confettiTrigger={confettiTrigger}
                setConfettiTrigger={setConfettiTrigger}
                setLogoutConfirm={setLogoutConfirm}
              />
            </RequireAuth>
          }
        >
          <Route index element={<Navigate to="/dashboard" replace/>}/>
          <Route path="/dashboard" element={<DashboardPage/>}/>
          <Route path="/leaderboard" element={<LeaderboardPage/>}/>
          <Route path="/members" element={<MembersPage/>}/>
          <Route path="/entry" element={<EntryPage/>}/>
          <Route path="/manage" element={<ManagePage/>}/>
          <Route path="/masters" element={<MastersPage/>}/>
          <Route path="/h2h" element={<H2HPage/>}/>
          <Route path="/history" element={<HistoryPage/>}/>
          <Route path="/recap" element={<RecapPage/>}/>
          <Route path="/teams/:teamId" element={<TeamPage/>}/>
          <Route path="/teams/:teamId/members/:memberName" element={<MemberPage/>}/>
        </Route>
        <Route path="*" element={<Navigate to="/dashboard" replace/>}/>
      </Routes>

      {logoutConfirm && (
        <div style={{
          position: "fixed", inset: 0, zIndex: 5000,
          background: "rgba(0,0,0,.45)",
          display: "grid", placeItems: "center",
          padding: 16,
        }} onClick={() => setLogoutConfirm(false)}>
          <div onClick={e => e.stopPropagation()} role="dialog" aria-modal="true" style={{
            background: "var(--bg-card)", color: "var(--ink)",
            borderRadius: 14, border: "1px solid var(--line)",
            width: "100%", maxWidth: 380, padding: 24,
            boxShadow: "0 24px 60px rgba(0,0,0,.35)",
          }}>
            <div style={{
              width: 44, height: 44, borderRadius: "50%",
              background: "rgba(178,30,46,.12)", color: "var(--crimson)",
              display: "grid", placeItems: "center", marginBottom: 14,
            }}>
              <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <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>
            </div>
            <h3 style={{ fontSize: 18, fontWeight: 700, marginBottom: 6 }}>Sign out?</h3>
            <p style={{ fontSize: 13, color: "var(--ink-mute)", marginBottom: 20, lineHeight: 1.5 }}>
              You'll need to sign in again to access the admin console.
            </p>
            <div style={{ display: "flex", gap: 10, justifyContent: "flex-end" }}>
              <button className="btn" onClick={() => setLogoutConfirm(false)}>Cancel</button>
              <button className="btn btn-primary" onClick={() => { setLogoutConfirm(false); auth.logout(); }}>Sign out</button>
            </div>
          </div>
        </div>
      )}
    </BrowserRouter>
  );
}

window.App = App;
