// app.jsx - main shell

const ACCENT = '#1025A1';

function App() {
  const [route, setRoute] = React.useState('home');
  const [openAsset, setOpenAsset] = React.useState(null);
  const [openProject, setOpenProject] = React.useState(null);
  const [showNewRecorder, setShowNewRecorder] = React.useState(false);
  const [dataReady, setDataReady] = React.useState(false);
  const [loadError, setLoadError] = React.useState(null);
  const [sidebarCollapsed, setSidebarCollapsed] = React.useState(() => {
    try {
      const stored = localStorage.getItem('df.sidebar.collapsed');
      if (stored != null) return stored === '1';
      // Default: collapsed on mobile, expanded on desktop.
      return typeof window !== 'undefined' && window.matchMedia && window.matchMedia('(max-width: 768px)').matches;
    } catch { return false; }
  });
  const toggleSidebar = React.useCallback(() => {
    setSidebarCollapsed(prev => {
      const next = !prev;
      try { localStorage.setItem('df.sidebar.collapsed', next ? '1' : '0'); } catch {}
      return next;
    });

  // Sync route state with URL hash
  React.useEffect(() => {
    const parseHash = () => {
      const hash = window.location.hash.slice(1); // remove #
      const route = hash.startsWith('/') ? hash.slice(1) : hash || 'home';
      setRoute(route);
    };
    parseHash();
    window.addEventListener('hashchange', parseHash);
    return () => window.removeEventListener('hashchange', parseHash);
  }, []);
  }, []);

  React.useEffect(() => {
    document.documentElement.style.setProperty('--accent', ACCENT);
    document.documentElement.style.setProperty('--accent-soft', hexToRgba(ACCENT, 0.14));
    document.documentElement.style.setProperty('--accent-soft-2', hexToRgba(ACCENT, 0.22));
    document.documentElement.style.setProperty('--accent-text', '#C7CFEA'); // Halo — readable on dark
    document.documentElement.style.setProperty('--accent-hover', '#1830B8');
  }, []);

  React.useEffect(() => {
    window.ZAMPP_API.loadData()
      .then(() => setDataReady(true))
      .catch(err => { console.error('[Dragonflight] load failed:', err); setLoadError(err.message || 'Failed to load'); setDataReady(true); });
  }, []);

  const navigate = (id) => { setOpenAsset(null); setRoute(id); };

  // Window-level nav event so deeply nested components (like the Tokens
  // "see the parody" link) can route without prop drilling.
  React.useEffect(() => {
    const handler = (e) => { if (e && e.detail) navigate(e.detail); };
    window.addEventListener('df:nav', handler);
    return () => window.removeEventListener('df:nav', handler);
  }, []);
  const openProjectFromAnywhere = (p) => { setOpenAsset(null); setOpenProject(p); setRoute('library'); };

  const crumbs = React.useMemo(() => {
    if (openAsset) return [
      { label: 'Library', to: 'library' },
      { label: openAsset.project || 'Library', to: 'library' },
      { label: openAsset.name },
    ];
    if (openProject) return [
      { label: 'Projects', to: 'projects' },
      { label: openProject.name },
    ];
    const labels = {
      home: ['Home'], dashboard: ['Dashboard'],
      library: ['Library'], projects: ['Projects'],
      upload: ['Ingest', 'Upload'], recorders: ['Ingest', 'Recorders'],
      schedule: ['Ingest', 'Schedule'],
      youtube: ['Ingest', 'YouTube'],
      capture: ['Ingest', 'Capture'], monitors: ['Ingest', 'Monitors'],
      jobs: ['Jobs'], editor: ['Editor'], playout: ['Operations', 'Playout'],
      users: ['Admin', 'Users & Groups'], tokens: ['Admin', 'Tokens'],
      containers: ['Admin', 'Containers'], cluster: ['Admin', 'Cluster'],
      settings: ['Admin', 'Settings'],
    };
    return (labels[route] || ['Home']).map(label => ({ label }));
  }, [route, openAsset, openProject]);

  if (!dataReady) {
    return (
      <>
        <style>{'@keyframes _df_spin{to{transform:rotate(360deg)}}'}</style>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100vh', flexDirection: 'column', gap: 14, background: 'var(--bg-0)' }}>
          <div style={{ width: 28, height: 28, borderRadius: '50%', border: '2px solid var(--border)', borderTopColor: ACCENT, animation: '_df_spin 0.8s linear infinite' }} />
          <div style={{ fontSize: 12, color: 'var(--text-3)', fontFamily: 'var(--font-mono)' }}>Loading Dragonflight…</div>
        </div>
      </>
    );
  }

  if (loadError) {
    return (
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100vh', flexDirection: 'column', gap: 12, background: 'var(--bg-0)' }}>
        <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--danger)' }}>Failed to load</div>
        <div style={{ fontSize: 12, color: 'var(--text-3)', maxWidth: 360, textAlign: 'center' }}>{loadError}</div>
        <button className="btn primary sm" onClick={() => window.location.reload()}>Retry</button>
      </div>
    );
  }

  // Admin-only destinations. Non-admins who reach one (deep link, keyboard
  // router, stale tab) get bounced home instead of a broken/forbidden page.
  // The API enforces the same rules — this is just UX.
  const ADMIN_ROUTES = new Set(['users', 'containers', 'cluster', 'settings']);
  const isAdmin = window.ZAMPP_DATA?.ME?.role === 'admin';
  const effectiveRoute = (ADMIN_ROUTES.has(route) && !isAdmin) ? 'home' : route;

  let content;
  if (openAsset) {
    content = <AssetDetail asset={openAsset} onClose={() => setOpenAsset(null)} />;
  } else {
    switch (effectiveRoute) {
      case 'home':       content = <Home navigate={navigate} />; break;
      case 'dashboard':  content = <Dashboard navigate={navigate} />; break;
      case 'library':   content = <Library navigate={navigate} onOpenAsset={setOpenAsset} openProject={openProject} onClearProject={() => setOpenProject(null)} />; break;
      case 'projects':  content = <Projects navigate={navigate} onOpenProject={openProjectFromAnywhere} />; break;
      case 'upload':    content = <Upload navigate={navigate} />; break;
      case 'recorders': content = <Recorders navigate={navigate} onNew={() => setShowNewRecorder(true)} />; break;
      case 'schedule':  content = <Schedule navigate={navigate} />; break;
      case 'youtube':   content = <YouTubeImport navigate={navigate} />; break;
      case 'capture':   content = <Capture navigate={navigate} />; break;
      case 'monitors':  content = <Monitors navigate={navigate} />; break;
      case 'jobs':      content = <Jobs navigate={navigate} />; break;
      case 'playout':   content = <Playout navigate={navigate} />; break;
      case 'users':     content = <Users />; break;
      case 'tokens':    content = <Tokens />; break;
      case 'billing':   content = <TokensParody />; break;
      case 'containers':content = <Containers />; break;
      case 'cluster':   content = <Cluster />; break;
      case 'settings':  content = <Settings />; break;
      default:          content = <Home navigate={navigate} />;
    }
  }

  // Home (launcher) suppresses the topbar - it's a full-bleed landing page.
  const hideTopbar = !openAsset && route === 'home';

  return (
    <div className="app" data-density="comfortable" data-grid-size="md" data-sidebar={sidebarCollapsed ? 'collapsed' : 'expanded'}>
      <Sidebar active={openAsset ? 'library' : route} onNavigate={navigate} me={window.ZAMPP_DATA?.ME} collapsed={sidebarCollapsed} onToggle={toggleSidebar} />
      <div className="main">
        {!openAsset && !hideTopbar && (
          <Topbar
            crumbs={crumbs}
            onNavigate={navigate}
            onOpenAsset={setOpenAsset}
            onOpenProject={openProjectFromAnywhere}
            onToggleSidebar={toggleSidebar}
          />
        )}
        {content}
      </div>
      {showNewRecorder && <NewRecorderModal open={showNewRecorder} onClose={() => setShowNewRecorder(false)} />}
    </div>
  );
}

function hexToRgba(hex, a) {
  const h = hex.replace('#', '');
  const r = parseInt(h.slice(0, 2), 16);
  const g = parseInt(h.slice(2, 4), 16);
  const b = parseInt(h.slice(4, 6), 16);
  return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
}
function lighten(hex, amt) {
  const h = hex.replace('#', '');
  const r = Math.min(255, parseInt(h.slice(0, 2), 16) + Math.round(amt * 255));
  const g = Math.min(255, parseInt(h.slice(2, 4), 16) + Math.round(amt * 255));
  const b = Math.min(255, parseInt(h.slice(4, 6), 16) + Math.round(amt * 255));
  return 'rgb(' + r + ',' + g + ',' + b + ')';
}

const root = ReactDOM.createRoot(document.getElementById('root'));
const AuthGate = window.AuthGateComponent;
root.render(<AuthGate><App /></AuthGate>);
