const { useState, useEffect, useMemo } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#a78bfa",
  "viz": "bars"
}/*EDITMODE-END*/;

const ACCENT_PRESETS = {
  '#f59e0b': '#fbbf24',  // amber
  '#a78bfa': '#c4b5fd',  // violet
  '#22d3ee': '#67e8f9',  // cyan
  '#34d399': '#6ee7b7',  // emerald
  '#f5f5f5': '#ffffff',  // monochrome
  '#fb7185': '#fda4af',  // rose
};

// ─── SPA routing ────────────────────────────────────────────────────────────
// Mirrors the admin pattern: keep one root mount, decide the view from the
// URL on every navigation, and use the History API so back/forward work
// without a full reload.

function viewFromUrl() {
  const p = window.location.pathname;
  if (p.startsWith('/incident'))    return 'incident';
  if (p.startsWith('/maintenance')) return 'maintenance';
  if (p.startsWith('/monitor'))     return 'monitor';
  return 'home';
}
function idFromUrl() {
  return new URLSearchParams(window.location.search).get('id');
}

function publicNavigate(view, params = null) {
  let url;
  if (view === 'incident'    && params?.id != null) url = '/incident/?id='    + params.id;
  else if (view === 'maintenance' && params?.id != null) url = '/maintenance/?id=' + params.id;
  else if (view === 'monitor'    && params?.id != null) url = '/monitor/?id='    + params.id;
  else url = '/';

  if (window.location.pathname + window.location.search === url) return;
  history.pushState({ view, id: params?.id ?? null }, '', url);
  window.dispatchEvent(new CustomEvent('public-navigate'));

  // Brief top-progress loader during the SPA hand-off. Fixed 400ms window
  // is long enough to register visually for fast/cached navigations; slower
  // destination pages render their own "Loading…" text once mounted.
  document.body.classList.add('is-navigating');
  clearTimeout(window.__publicNavTimer);
  window.__publicNavTimer = setTimeout(() => {
    document.body.classList.remove('is-navigating');
  }, 400);
}
window.publicNavigate = publicNavigate;

function PublicApp() {
  const [route, setRoute] = useState(() => ({ view: viewFromUrl(), id: idFromUrl() }));

  useEffect(() => {
    function sync() { setRoute({ view: viewFromUrl(), id: idFromUrl() }); }
    window.addEventListener('public-navigate', sync);
    window.addEventListener('popstate', sync);
    return () => {
      window.removeEventListener('public-navigate', sync);
      window.removeEventListener('popstate', sync);
    };
  }, []);

  // Scroll to top on view change so a detail page doesn't open mid-page.
  useEffect(() => { window.scrollTo(0, 0); }, [route.view, route.id]);

  if (route.view === 'incident')    return <IncidentPage    key={'i' + route.id}   id={route.id} />;
  if (route.view === 'maintenance') return <MaintenancePage key={'m' + route.id}   id={route.id} />;
  if (route.view === 'monitor')     return <MonitorPage     key={'mon' + route.id} id={route.id} />;
  return <HomeView />;
}

// ─── Home view ──────────────────────────────────────────────────────────────

function HomeView() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [range, setRange] = useState('1h');
  const [now, setNow] = useState(new Date());
  const [data, setData] = useState({
    services: [], activeIncidents: [], pastIncidents: [], activeMaintenance: [], maintenance: [], pastMaintenance: [], overall: 'operational',
  });
  // Only tracks the *initial* load — interval refreshes don't flip this back to true.
  const [isLoading, setIsLoading] = useState(true);

  // Live ticking clock
  useEffect(() => {
    const i = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(i);
  }, []);

  // Pull rollup from API on mount; refresh every 30s.
  useEffect(() => {
    let initial = true;
    function load() {
      apiFetch('/api/status.php')
        .then(d => { setData(d); if (initial) { setIsLoading(false); initial = false; } })
        .catch(err => { console.error('Failed to load status:', err); if (initial) { setIsLoading(false); initial = false; } });
    }
    load();
    const i = setInterval(load, 30000);
    return () => clearInterval(i);
  }, []);

  // Show the top progress bar only if loading exceeds 200ms — fast loads don't flash.
  useEffect(() => {
    if (!isLoading) { document.body.classList.remove('is-loading'); return undefined; }
    const t = setTimeout(() => document.body.classList.add('is-loading'), 200);
    return () => clearTimeout(t);
  }, [isLoading]);

  // Apply accent
  useEffect(() => {
    document.documentElement.style.setProperty('--accent',   t.accent);
    document.documentElement.style.setProperty('--accent-2', ACCENT_PRESETS[t.accent] || t.accent);
    document.documentElement.style.setProperty('--accent-soft', t.accent + '22');
  }, [t.accent]);

  // Most-recent probe timestamp across all monitors. Changes whenever any
  // monitor records a fresh check — used by the header to pulse its dot once.
  const monitorTick = useMemo(() =>
    (data.services || []).reduce((max, s) => {
      const v = s.lastCheckedAt ? new Date(s.lastCheckedAt).getTime() : 0;
      return v > max ? v : max;
    }, 0),
    [data.services]
  );

  return (
    <React.Fragment>
      <Header now={now} monitorTick={monitorTick} />
      <main className="shell">
        {data.probesStale && (
          <StaleBanner proberLastSuccessAt={data.proberLastSuccessAt} now={now} />
        )}
        <OverallBanner
          services={data.services}
          uptime={data.uptime}
          proberLastSuccessAt={data.proberLastSuccessAt}
          probesStale={data.probesStale}
          activeMaintenance={data.activeMaintenance}
          now={now}
        />
        {(data.activeIncidents || []).map(inc => (
          <ActiveIncident key={inc.id} incident={inc} now={now} />
        ))}
        <ActiveMaintenance maintenance={data.activeMaintenance} now={now} />
        <ServicesSection
          services={data.services}
          viz={t.viz}
          range={range}
          setRange={setRange}
          probesStale={data.probesStale}
        />
        <MetricsSection metrics={data.metrics} range={range} />
        <MaintenanceSection maintenance={data.maintenance} />
        <PastIncidents incidents={data.pastIncidents} />
        <MaintenanceHistory maintenance={data.pastMaintenance} />
        <Footer />
      </main>

      <TweaksPanel title="Tweaks">
        <TweakSection label="Appearance" />
        <TweakColor
          label="Accent"
          value={t.accent}
          options={['#f59e0b', '#a78bfa', '#22d3ee', '#34d399', '#fb7185', '#f5f5f5']}
          onChange={(v) => setTweak('accent', v)}
        />
        <TweakSection label="Uptime history" />
        <TweakRadio
          label="Style"
          value={t.viz}
          options={[
            { value: 'bars', label: 'Bars' },
            { value: 'dots', label: 'Dots' },
            { value: 'line', label: 'Line' },
            { value: 'pill', label: 'Pill' },
          ]}
          onChange={(v) => setTweak('viz', v)}
        />
      </TweaksPanel>
    </React.Fragment>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<PublicApp />);
