// JARVIS v3 — main app shell with hash-based routing + live data fetch

const { useState, useEffect, useCallback } = React;

const ROUTES = {
  overview:  { label: "Overview",         Comp: () => window.OverviewV3  },
  finances:  { label: "Finances",         Comp: () => window.FinancesPage },
  academics: { label: "Academics",        Comp: () => window.AcademicsPage },
  ventures:  { label: "Ventures",         Comp: () => window.VenturesPage },
  family:    { label: "Child Development",Comp: () => window.FamilyPage },
  calendar:  { label: "Calendar",        Comp: () => window.CalendarPage },
  health:    { label: "Health",           Comp: () => window.HealthPage },
  projects:  { label: "Projects",        Comp: () => window.ProjectsPage },
  home:      { label: "Home Value",      Comp: () => window.HomeValuePage },
  chat:      { label: "JARVIS Chat",     Comp: () => window.ChatPage },
  inbox:     { label: "Action Inbox",    Comp: () => window.InboxPage }
};

// Fetches live data from backend API and merges into window.JARVIS_DATA
async function fetchLiveData(onUpdate) {
  const D = window.JARVIS_DATA;
  const token = sessionStorage.getItem("jarvis.mobile.token") || sessionStorage.getItem("jarvis_token");
  if (token) window.__jarvisAuthToken = token;
  const headers = token ? { "x-jarvis-auth": token } : {};

  try {
    const [dataRes, calRes, ccRes] = await Promise.allSettled([
      fetch("/api/data",                 { headers }),
      fetch("/api/calendar/data",        { headers }),
      fetch("/api/finances/cc-paydown",  { headers })
    ]);

    // Main data endpoint
    if (dataRes.status === "fulfilled" && dataRes.value.ok) {
      const raw = await dataRes.value.json();

      // v2 legacy fields (other pages may still read these)
      if (raw.totals) {
        D.totals = raw.totals;
        if (D.metrics) {
          D.metrics.assets   = raw.totals.assets  || D.metrics.assets;
          D.metrics.liab     = raw.totals.debt     || D.metrics.liab;
          D.metrics.accounts = raw.totals.accounts || D.metrics.accounts;
        }
      }
      if (raw.status) {
        D.status = raw.status;
        if (raw.status.finance && D.metrics) {
          const fv = parseFloat(String(raw.status.finance.value || "").replace(/[^0-9.\-]/g, ""));
          if (!isNaN(fv)) D.metrics.netWorth = fv;
        }
      }
      if (raw.academics) {
        D.academics = raw.academics;
        if (raw.academics.gpa && D.metrics) D.metrics.gpa = raw.academics.gpa;
        if (raw.academics.courses) D.courses = raw.academics.courses;
      }
      if (raw.debt && raw.debt.items) {
        D.debt = raw.debt;
        // Map to liabilities format if present
        const items = raw.debt.items;
        if (items.length && D.liabilities) {
          items.forEach(item => {
            const existing = D.liabilities.find(l => l.name === item.name);
            if (existing && item.balance) existing.bal = item.balance;
          });
        }
      }
      if (raw.vehicles) D.vehicles = raw.vehicles;
      if (raw.home) {
        D.home = raw.home;
        if (raw.home.averageEstimate && D.metrics) D.metrics.homeValue = raw.home.averageEstimate;
      }
      if (raw.assets) {
        D.assets = raw.assets;
        // Update assetsList balances from live Fidelity data
        if (Array.isArray(raw.assets)) {
          raw.assets.forEach(liveAsset => {
            const existing = (D.assetsList || []).find(a => a.name === liveAsset.name);
            if (existing && liveAsset.balance) existing.bal = liveAsset.balance;
          });
        }
      }
      if (raw.ventures) {
        raw.ventures.forEach(lv => {
          const existing = (D.ventures || []).find(v => v.key === lv.key || v.name === lv.name);
          if (existing) {
            if (lv.mtd !== undefined) existing.mtd = lv.mtd;
            if (lv.ytd !== undefined) existing.ytd = lv.ytd;
          }
        });
        if (D.metrics) {
          D.metrics.mtdRev = (D.ventures || []).reduce((s, v) => s + (v.mtd || 0), 0);
          D.metrics.yrRev  = (D.ventures || []).reduce((s, v) => s + (v.ytd || 0), 0);
        }
      }
      if (raw.calendar) D.calendar = raw.calendar;
    }

    // Calendar data
    if (calRes.status === "fulfilled" && calRes.value.ok) {
      const cal = await calRes.value.json();
      if (cal && (cal.events || cal.items)) {
        const events = cal.events || cal.items || [];
        D.calendar = events;
        // Update schedule (next 4 events) for overview
        const now = Date.now();
        const upcoming = events
          .filter(e => new Date(e.start || e.date || 0).getTime() >= now)
          .slice(0, 4)
          .map((e, i) => ({
            id: "cal-" + i,
            time: new Date(e.start || e.date).toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" }),
            date: new Date(e.start || e.date).toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric" }),
            title: e.summary || e.title || e.name || "Event",
            ctx: e.description || e.location || e.calendar || ""
          }));
        if (upcoming.length) D.schedule = upcoming;
      }
    }

    // CC paydown data
    if (ccRes.status === "fulfilled" && ccRes.value.ok) {
      const cc = await ccRes.value.json();
      if (cc) {
        D.ccPayoff = cc;
        if (cc.currentBalance && D.metrics) {
          D.metrics.cc = cc.currentBalance;
        }
      }
    }

    if (onUpdate) onUpdate();
  } catch (err) {
    console.warn("[JARVIS] fetchLiveData error:", err);
  }
}

function App() {
  const initial = (window.location.hash || "#overview").replace("#", "");
  const [route, setRoute] = useState(ROUTES[initial] ? initial : "overview");
  const [collapsed, setCollapsed] = useState(() => {
    try { return localStorage.getItem("jarvis-sidebar-collapsed") === "1"; } catch { return false; }
  });
  const [, forceUpdate] = useState(0);
  const { theme, setTheme } = window.useTweaks ? window.useTweaks() : { theme: "light", setTheme: () => {} };

  const toggleCollapsed = () => {
    setCollapsed(c => {
      const next = !c;
      try { localStorage.setItem("jarvis-sidebar-collapsed", next ? "1" : "0"); } catch {}
      return next;
    });
  };

  useEffect(() => {
    const onHash = () => {
      const r = (window.location.hash || "#overview").replace("#", "");
      if (ROUTES[r]) setRoute(r);
    };
    window.addEventListener("hashchange", onHash);
    return () => window.removeEventListener("hashchange", onHash);
  }, []);

  // Load live data on mount; expose global so SyncButtons can trigger refresh
  useEffect(() => {
    const refresh = () => fetchLiveData(() => forceUpdate(n => n + 1));
    window.__jarvisRefresh = refresh;
    refresh();
    return () => { delete window.__jarvisRefresh; };
  }, []);

  const navigate = useCallback((id) => {
    if (!ROUTES[id]) return;
    window.location.hash = id;
    setRoute(id);
    const main = document.querySelector(".main");
    if (main) main.scrollTop = 0;
  }, []);

  // Keyboard shortcuts
  useEffect(() => {
    const keys = { "1": "overview", "2": "finances", "3": "academics", "4": "ventures", "5": "family", "6": "calendar", "7": "health", "8": "projects", "h": "home", "k": "chat", "i": "inbox" };
    const onKey = (e) => {
      if (e.metaKey || e.ctrlKey) {
        if (e.key === "\\") { e.preventDefault(); toggleCollapsed(); return; }
        const id = keys[e.key.toLowerCase()];
        if (id) { e.preventDefault(); navigate(id); }
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [navigate]);

  const routeDef = ROUTES[route];
  const Comp = routeDef.Comp();

  if (!Comp) {
    return (
      <div className="app">
        <div style={{padding: 40, color: "var(--fg-soft)"}}>Loading…</div>
      </div>
    );
  }

  return (
    <div className="app" data-theme={theme}>
      <TickerBar />
      <div className={"app-body" + (collapsed ? " sidebar-collapsed" : "")}>
        <Sidebar current={route} onNavigate={navigate} collapsed={collapsed} onToggleCollapsed={toggleCollapsed} />
        <button
          className="sidebar-collapse-btn"
          onClick={toggleCollapsed}
          title={collapsed ? "Expand sidebar (⌘\\)" : "Collapse sidebar (⌘\\)"}
        >
          <svg width="9" height="9" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
            <polyline points={collapsed ? "4,3 7,6 4,9" : "7,3 4,6 7,9"}/>
          </svg>
        </button>
        <main className="main">
          <Comp navigate={navigate} />
        </main>
        <MobileBottomNav current={route} onNavigate={navigate} />
      </div>
    </div>
  );
}

function MobileBottomNav({ current, onNavigate }) {
  const [menuOpen, setMenuOpen] = useState(false);
  const primary = [
    { id: "overview", label: "Overview", icon: "overview" },
    { id: "finances", label: "Finance", icon: "finance" },
    { id: "health", label: "Health", icon: "health" },
    { id: "family", label: "Family", icon: "family" }
  ];
  const menuItems = [
    { id: "academics", label: "Academics", icon: "academics" },
    { id: "ventures", label: "Ventures", icon: "ventures" },
    { id: "calendar", label: "Calendar", icon: "calendar" },
    { id: "projects", label: "Projects", icon: "projects" },
    { id: "home", label: "Home Value", icon: "home" },
    { id: "chat", label: "JARVIS Chat", icon: "chat" },
    { id: "inbox", label: "Action Inbox", icon: "inbox" }
  ];
  const primaryIds = primary.map(item => item.id);
  const menuActive = !primaryIds.includes(current);

  useEffect(() => {
    setMenuOpen(false);
  }, [current]);

  const go = (id) => {
    setMenuOpen(false);
    onNavigate(id);
  };

  return (
    <>
      {menuOpen && <button className="mobile-menu-backdrop" aria-label="Close menu" onClick={() => setMenuOpen(false)} />}
      <div id="mobile-menu" className={"mobile-menu-sheet" + (menuOpen ? " open" : "")} aria-hidden={!menuOpen}>
        <div className="mobile-menu-grid">
          {menuItems.map(item => (
            <button
              key={item.id}
              className={"mobile-menu-item" + (current === item.id ? " active" : "")}
              onClick={() => go(item.id)}
            >
              <span className="mobile-menu-icon"><NavIcon name={item.icon} /></span>
              <span>{item.label}</span>
            </button>
          ))}
        </div>
      </div>
      <nav className="mobile-bottom-nav" aria-label="Primary navigation">
        {primary.map(item => (
          <button
            key={item.id}
            className={"mobile-tab-btn" + (current === item.id ? " active" : "")}
            onClick={() => go(item.id)}
          >
            <span className="mobile-tab-icon"><NavIcon name={item.icon} /></span>
            <span>{item.label}</span>
          </button>
        ))}
        <button
          className={"mobile-tab-btn" + (menuActive || menuOpen ? " active" : "")}
          onClick={() => setMenuOpen(open => !open)}
          aria-expanded={menuOpen}
          aria-controls="mobile-menu"
        >
          <span className="mobile-tab-icon mobile-tab-menu-icon">
            <span />
            <span />
            <span />
          </span>
          <span>Menu</span>
        </button>
      </nav>
    </>
  );
}

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