// app.jsx — auth, routing, views, tweaks.
const { useState: useStateApp, useEffect: useEffectApp } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#2A6FDB",
  "density": "comfortable",
  "cardStyle": "shadowed",
  "semantic": true
}/*EDITMODE-END*/;

// label helpers (handle the special 'custom' period) -------------------------
function periodLabel(period) {
  return period === 'custom' ? 'Custom range' : window.PERIODS[period].label;
}
function rangeText(period, custom) {
  if (period === 'custom') return custom ? window.fmtRange(custom.from, custom.to) : 'Pick a range';
  return window.PERIODS[period].range;
}

// ---- shared header controls ------------------------------------------------
function HeaderControls({ period, onPeriod, custom, onCustom, chrome }) {
  return (
    <div className="topbar-right">
      {chrome.dataKind === 'mock' && <span className="data-badge" title="Couldn't reach Supabase — showing demo data">Demo data</span>}
      <span className="period-range">{rangeText(period, custom)}</span>
      <window.DateFilter period={period} onPeriod={onPeriod} custom={custom} onCustom={onCustom} />
      {chrome.account && <window.AccountChip email={chrome.account} onSignOut={chrome.onSignOut} />}
    </div>
  );
}

// ---- roll-up view ----------------------------------------------------------
function RollupView({ source, period, onPeriod, onOpen, semantic, custom, onCustom, chrome }) {
  const { total, rows } = source.rollup(period, custom);
  return (
    <div className="view">
      <header className="topbar">
        <div className="brand">
          <div className="brand-mark" aria-hidden="true"><span></span><span></span><span></span></div>
          <div className="brand-text"><span className="brand-name">WEBRIS</span></div>
        </div>
        <HeaderControls period={period} onPeriod={onPeriod} custom={custom} onCustom={onCustom} chrome={chrome} />
      </header>
      <main className="content">
        <div className="page-head">
          <div>
            <h1 className="page-title">Portfolio overview</h1>
            <p className="page-sub">{rows.length} active clients · {periodLabel(period).toLowerCase()} roll-up across all accounts</p>
          </div>
        </div>
        <window.MetricRow m={total} semantic={semantic} />
        <window.ClientTable rows={rows} onOpen={onOpen} />
      </main>
    </div>
  );
}

// ---- individual client view ------------------------------------------------
function ClientView({ source, clientId, period, onPeriod, onBack, semantic, custom, onCustom, chrome }) {
  const client = source.getClient(clientId);
  if (!client) { return <div className="view"><main className="content"><p className="page-sub">Client not found. <button className="link-btn" onClick={onBack}>Back to all clients</button></p></main></div>; }
  const m = source.clientMetrics(clientId, period, custom);
  return (
    <div className="view">
      <header className="topbar">
        <button className="back-btn" onClick={onBack}>
          <span aria-hidden="true">←</span> All clients
        </button>
        <HeaderControls period={period} onPeriod={onPeriod} custom={custom} onCustom={onCustom} chrome={chrome} />
      </header>
      <main className="content">
        <div className="page-head">
          <div>
            <div className="client-eyebrow">
              <window.CrmBadge type={client.crm_type} />
              {client.region ? <span className="cregion">{client.region}</span> : null}
            </div>
            <h1 className="page-title">{client.name}</h1>
            <p className="page-sub">{periodLabel(period)} performance · leads, conversions &amp; contract status</p>
          </div>
        </div>

        <window.MetricRow m={m} semantic={semantic} />

        <div className="panel">
          <div className="panel-head">
            <div className="panel-titles">
              <h2 className="panel-title">Leads by source</h2>
              <span className="panel-count">{window.fmt(m.leads_generated)} total leads</span>
            </div>
          </div>
          <div className="source-grid">
            <window.SourceCard label="Calls"      value={m.calls}      total={m.leads_generated} prev={m.prev.calls}      hint="of total leads" />
            <window.SourceCard label="Form Fills" value={m.form_fills} total={m.leads_generated} prev={m.prev.form_fills} hint="of total leads" />
            <window.SourceCard label="Chats"      value={m.chats}      total={m.leads_generated} prev={m.prev.chats}      hint="of total leads" />
          </div>
        </div>
      </main>
    </div>
  );
}

// ---- tweaks ----------------------------------------------------------------
function applyTokens(t) {
  const root = document.documentElement;
  root.style.setProperty('--accent', t.accent);
  root.dataset.density = t.density;
  root.dataset.card = t.cardStyle;
  root.dataset.semantic = t.semantic ? 'on' : 'off';
}

function Tweaks({ t, setTweak }) {
  return (
    <window.TweaksPanel>
      <window.TweakSection label="Brand" />
      <window.TweakColor label="Accent" value={t.accent}
        options={['#2A6FDB', '#4F46E5', '#0F172A', '#1F8A5B']}
        onChange={(v) => setTweak('accent', v)} />
      <window.TweakSection label="Layout" />
      <window.TweakRadio label="Density" value={t.density}
        options={['compact', 'comfortable']}
        onChange={(v) => setTweak('density', v)} />
      <window.TweakRadio label="Cards" value={t.cardStyle}
        options={['bordered', 'filled', 'shadowed']}
        onChange={(v) => setTweak('cardStyle', v)} />
      <window.TweakSection label="Data" />
      <window.TweakToggle label="Semantic color" value={t.semantic}
        onChange={(v) => setTweak('semantic', v)} />
    </window.TweaksPanel>
  );
}

// ---- loading splash --------------------------------------------------------
function Splash({ label }) {
  return (
    <div className="splash">
      <div className="brand-mark splash-mark" aria-hidden="true"><span></span><span></span><span></span></div>
      <span className="splash-label">{label}</span>
    </div>
  );
}

// ---- app shell -------------------------------------------------------------
function App() {
  const [t, setTweak] = window.useTweaks(TWEAK_DEFAULTS);
  const [period, setPeriod] = useStateApp(() => {
    const saved = localStorage.getItem('np_period');
    return (saved === 'custom' || window.PERIOD_KEYS.includes(saved)) ? saved : 'monthly';
  });
  const [custom, setCustom] = useStateApp(() => {
    try { return JSON.parse(localStorage.getItem('np_custom')) || null; } catch { return null; }
  });
  const [route, setRoute] = useStateApp(() => {
    try { return JSON.parse(localStorage.getItem('np_route')) || { view: 'rollup' }; }
    catch { return { view: 'rollup' }; }
  });

  // ---- auth + data source ----
  const [authReady, setAuthReady] = useStateApp(false);
  const [session, setSession] = useStateApp(null);
  const [source, setSource] = useStateApp(null);
  const [dataKind, setDataKind] = useStateApp('live');
  const [loadingData, setLoadingData] = useStateApp(false);

  useEffectApp(() => { applyTokens(t); }, [t]);
  useEffectApp(() => { localStorage.setItem('np_period', period); }, [period]);
  useEffectApp(() => { localStorage.setItem('np_custom', JSON.stringify(custom)); }, [custom]);
  useEffectApp(() => { localStorage.setItem('np_route', JSON.stringify(route)); }, [route]);

  // init auth (or skip straight to mock if Supabase isn't configured)
  useEffectApp(() => {
    if (!window.SUPABASE_CONFIGURED) {
      setSource(window.makeMockSource()); setDataKind('mock'); setAuthReady(true);
      return;
    }
    window.sb.auth.getSession().then(({ data }) => { setSession(data.session); setAuthReady(true); });
    const { data: sub } = window.sb.auth.onAuthStateChange((_e, s) => { setSession(s); });
    return () => { sub.subscription.unsubscribe(); };
  }, []);

  // load live data once signed in; fall back to mock on any failure
  useEffectApp(() => {
    if (!window.SUPABASE_CONFIGURED) return;
    if (!session) { setSource(null); return; }
    let cancelled = false;
    setLoadingData(true);
    window.loadLiveSource()
      .then((src) => { if (!cancelled) { setSource(src); setDataKind('live'); } })
      .catch((err) => {
        if (cancelled) return;
        console.warn('Supabase load failed — using demo data:', err && err.message);
        setSource(window.makeMockSource()); setDataKind('mock');
      })
      .finally(() => { if (!cancelled) setLoadingData(false); });
    return () => { cancelled = true; };
  }, [session]);

  const signOut = async () => {
    try { await window.sb.auth.signOut(); } catch (e) { /* ignore */ }
    setSession(null); setSource(null);
  };

  const open = (id) => { setRoute({ view: 'client', clientId: id }); window.scrollTo(0, 0); };
  const back = () => { setRoute({ view: 'rollup' }); window.scrollTo(0, 0); };

  // ---- render gates ----
  if (!authReady) return <Splash label="Loading…" />;
  if (window.SUPABASE_CONFIGURED && !session) {
    // No session — send the user to the dedicated AUTH page.
    window.location.replace('AUTH.html');
    return <Splash label="Redirecting to sign in…" />;
  }
  if (!source || loadingData) return <Splash label="Loading your dashboard…" />;

  const chrome = { account: session && session.user ? session.user.email : null, onSignOut: signOut, dataKind };

  return (
    <React.Fragment>
      {route.view === 'rollup'
        ? <RollupView source={source} period={period} onPeriod={setPeriod} onOpen={open} semantic={t.semantic} custom={custom} onCustom={setCustom} chrome={chrome} />
        : <ClientView source={source} clientId={route.clientId} period={period} onPeriod={setPeriod} onBack={back} semantic={t.semantic} custom={custom} onCustom={setCustom} chrome={chrome} />}
      <Tweaks t={t} setTweak={setTweak} />
    </React.Fragment>
  );
}

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