// Main app shell — gated behind Supabase auth + initial data load.

const NAV_ITEMS = [
  { id: "overview", label: "Overview", icon: "home" },
  { id: "transactions", label: "Transactions", icon: "list" },
  { id: "cards", label: "Cards & Miles", icon: "card" },
  { id: "accounts", label: "Accounts", icon: "wallet" },
  { id: "insights", label: "Insights", icon: "chart" },
];

function App() {
  const [session, setSession] = React.useState(null);
  const [authChecked, setAuthChecked] = React.useState(false);
  const [dataReady, setDataReady] = React.useState(false);
  const [loadError, setLoadError] = React.useState(null);
  const [refreshKey, setRefreshKey] = React.useState(0);

  // ── Auth wiring ────────────────────────────────────────────────────────────
  React.useEffect(() => {
    let mounted = true;

    // Restore session from localStorage on mount
    window.sb.auth.getSession().then(({ data, error }) => {
      if (!mounted) return;
      if (error) console.error("getSession error:", error);
      setSession(data?.session ?? null);
      setAuthChecked(true);
    });

    // Subscribe to auth state changes (sign in, sign out, token refresh)
    const { data: { subscription } } = window.sb.auth.onAuthStateChange((_event, newSession) => {
      if (!mounted) return;
      setSession(newSession);
      if (!newSession) {
        // Signed out — reset data state so next sign-in re-fetches
        setDataReady(false);
        setLoadError(null);
      }
    });

    return () => { mounted = false; subscription.unsubscribe(); };
  }, []);

  // ── Data loading (after auth) ──────────────────────────────────────────────
  React.useEffect(() => {
    if (!session) return;
    let cancelled = false;
    setLoadError(null);
    setDataReady(false);
    window.loadAllData()
      .then(() => { if (!cancelled) setDataReady(true); })
      .catch(err => { if (!cancelled) setLoadError(err.message || "Failed to load data."); });
    return () => { cancelled = true; };
  }, [session, refreshKey]);

  // Expose refetch globally so the Add Transaction modal can trigger a refresh
  React.useEffect(() => {
    window.refetchData = () => setRefreshKey(k => k + 1);
    return () => { delete window.refetchData; };
  }, []);

  const handleSignOut = async () => {
    await window.sb.auth.signOut();
  };

  // ── Render gate ────────────────────────────────────────────────────────────
  if (!authChecked) return <LoadingScreen message="Checking session…"/>;
  if (!session) return <LoginScreen/>;
  if (loadError) return <ErrorScreen message={loadError} onRetry={() => setRefreshKey(k => k + 1)} onSignOut={handleSignOut}/>;
  if (!dataReady) return <LoadingScreen message="Loading your data…"/>;

  return <AuthenticatedApp onSignOut={handleSignOut}/>;
}

function AuthenticatedApp({ onSignOut }) {
  const [tweaks, setTweak] = useTweaks(window.TWEAK_DEFAULTS);
  const [view, setView] = React.useState("overview");
  const [showAdd, setShowAdd] = React.useState(false);

  React.useEffect(() => {
    document.documentElement.setAttribute("data-theme", tweaks.theme);
    document.documentElement.setAttribute("data-density", tweaks.density);
    document.documentElement.setAttribute("data-accent", tweaks.accent);
  }, [tweaks.theme, tweaks.density, tweaks.accent]);

  const handleNav = (id) => {
    if (id === "add") { setShowAdd(true); return; }
    setView(id);
  };

  return (
    <div style={{ minHeight: "100vh", background: "var(--bg-app)", color: "var(--text-1)" }}>
      <div style={{ display: "flex", minHeight: "100vh" }}>
        <Sidebar view={view} onNav={handleNav} collapsed={tweaks.navCollapsed} onSignOut={onSignOut}/>
        <main className="main-content" style={{ flex: 1, minWidth: 0, display: "flex", flexDirection: "column" }}>
          <TopBar onAdd={() => setShowAdd(true)} tweaks={tweaks} setTweak={setTweak}/>
          <div style={{ padding: tweaks.density === "compact" ? "20px 28px 40px" : "28px 36px 48px", maxWidth: 1400, width: "100%", margin: "0 auto", boxSizing: "border-box" }}>
            {view === "overview" && <OverviewView onNav={handleNav} layout={tweaks.overviewLayout}/>}
            {view === "transactions" && <TransactionsView/>}
            {view === "cards" && <CardsView/>}
            {view === "accounts" && <AccountsView transferStyle={tweaks.transferStyle} reimbStyle={tweaks.reimbStyle}/>}
            {view === "insights" && <InsightsView/>}
          </div>
        </main>
      </div>

      {showAdd && <AddTransactionModal onClose={() => setShowAdd(false)} onSaved={() => { setShowAdd(false); window.refetchData?.(); }}/>}

      <TweaksPanel title="Tweaks">
        <TweakSection title="Appearance">
          <TweakRadio label="Theme" value={tweaks.theme} options={[{value: "light", label: "Light"}, {value: "dark", label: "Dark"}]} onChange={v => setTweak("theme", v)}/>
          <TweakRadio label="Accent" value={tweaks.accent} options={[
            { value: "mono", label: "Mono" },
            { value: "indigo", label: "Indigo" },
            { value: "emerald", label: "Emerald" },
            { value: "amber", label: "Amber" },
            { value: "rose", label: "Rose" },
          ]} onChange={v => setTweak("accent", v)}/>
          <TweakRadio label="Density" value={tweaks.density} options={[{value: "comfortable", label: "Comfy"}, {value: "compact", label: "Compact"}]} onChange={v => setTweak("density", v)}/>
        </TweakSection>
        <TweakSection title="Overview layout">
          <TweakRadio label="Layout" value={tweaks.overviewLayout} options={[
            { value: "balanced", label: "Balanced" },
            { value: "chart", label: "Chart-heavy" },
            { value: "list", label: "List-heavy" },
          ]} onChange={v => setTweak("overviewLayout", v)}/>
        </TweakSection>
        <TweakSection title="Transfers & reimbursements (Accounts page)">
          <TweakRadio label="Transfer style" value={tweaks.transferStyle} options={[
            { value: "linked", label: "Linked" },
            { value: "split", label: "Split entries" },
          ]} onChange={v => setTweak("transferStyle", v)}/>
          <TweakRadio label="Reimbursement style" value={tweaks.reimbStyle} options={[
            { value: "tagged", label: "Status tag" },
            { value: "auto", label: "Auto-net" },
          ]} onChange={v => setTweak("reimbStyle", v)}/>
        </TweakSection>
        <TweakSection title="Layout">
          <TweakToggle label="Collapse sidebar" value={tweaks.navCollapsed} onChange={v => setTweak("navCollapsed", v)}/>
        </TweakSection>
      </TweaksPanel>
    </div>
  );
}

function Sidebar({ view, onNav, collapsed, onSignOut }) {
  return (
    <aside className="sidebar" style={{
      width: collapsed ? 64 : 220,
      flexShrink: 0,
      background: "var(--bg)",
      borderRight: "1px solid var(--border)",
      display: "flex", flexDirection: "column",
      padding: collapsed ? "20px 8px" : "20px 14px",
      gap: 4,
      transition: "width 0.18s",
      position: "sticky", top: 0, height: "100vh",
    }}>
      <div style={{
        display: "flex", alignItems: "center", gap: 10,
        padding: collapsed ? "6px 6px 14px" : "6px 8px 18px",
        borderBottom: "1px solid var(--border-subtle)",
        marginBottom: 8,
      }}>
        <div style={{
          width: 30, height: 30, borderRadius: 8,
          background: "var(--text-1)",
          display: "grid", placeItems: "center",
          color: "var(--bg)", flexShrink: 0,
          fontWeight: 700, fontSize: 14,
        }}>L</div>
        {!collapsed && <div style={{ fontSize: 14, fontWeight: 700, color: "var(--text-1)", letterSpacing: "-0.01em" }}>Ledger</div>}
      </div>

      {NAV_ITEMS.map(item => {
        const active = view === item.id;
        return (
          <button key={item.id} onClick={() => onNav(item.id)} className={"nav-item " + (active ? "nav-active" : "")} title={collapsed ? item.label : undefined}>
            <Icon name={item.icon} size={16}/>
            {!collapsed && <span>{item.label}</span>}
          </button>
        );
      })}

      <div style={{ flex: 1 }}/>

      {!collapsed && (
        <div style={{ padding: 12, borderRadius: 10, background: "var(--bg-muted)", marginBottom: 8 }}>
          <div style={{ fontSize: 11, color: "var(--text-muted)", fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: 6 }}>This month</div>
          <div style={{ fontSize: 13, fontWeight: 600, color: "var(--text-1)", fontVariantNumeric: "tabular-nums", marginBottom: 4 }}>
            {fmt.sgd(sumExpensesThisMonth(), { decimals: 0 })} spent
          </div>
          <div style={{ fontSize: 10.5, color: "var(--text-muted)" }}>
            {fmt.sgd(sumIncomeThisMonth(), { decimals: 0 })} income
          </div>
        </div>
      )}

      <button onClick={onSignOut} className="nav-item" title={collapsed ? "Sign out" : undefined}>
        <Icon name="log-out" size={16}/>
        {!collapsed && <span>Sign out</span>}
      </button>
    </aside>
  );
}

function TopBar({ onAdd, tweaks, setTweak }) {
  return (
    <header style={{
      height: 56,
      borderBottom: "1px solid var(--border)",
      background: "var(--bg)",
      display: "flex", alignItems: "center",
      padding: "0 28px",
      gap: 16,
      position: "sticky", top: 0, zIndex: 10,
    }}>
      <div className="topbar-search" style={{ position: "relative", flex: 1, maxWidth: 360 }}>
        <Icon name="search" size={14} style={{ position: "absolute", left: 12, top: "50%", transform: "translateY(-50%)", color: "var(--text-muted)" }}/>
        <input
          placeholder="Search transactions, merchants, cards…"
          style={{
            width: "100%", padding: "8px 12px 8px 34px",
            background: "var(--bg-muted)", border: "1px solid transparent",
            borderRadius: 8, fontSize: 13, color: "var(--text-1)", outline: "none",
            fontFamily: "inherit",
          }}/>
        <kbd className="topbar-extra" style={{ position: "absolute", right: 10, top: "50%", transform: "translateY(-50%)", fontSize: 10, padding: "2px 5px", borderRadius: 3, background: "var(--bg)", border: "1px solid var(--border-subtle)", color: "var(--text-muted)", fontFamily: "var(--font-mono)" }}>⌘K</kbd>
      </div>

      <div style={{ flex: 1 }}/>

      <button className="btn-ghost-sm" onClick={() => setTweak("theme", tweaks.theme === "dark" ? "light" : "dark")}>
        <Icon name={tweaks.theme === "dark" ? "sun" : "moon"} size={15}/>
      </button>
      <button className="btn-ghost-sm topbar-extra"><Icon name="bell" size={15}/></button>
      <button className="btn-primary" onClick={onAdd}>
        <Icon name="plus" size={14}/> Add
      </button>
    </header>
  );
}

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