// App — top-level router, owns app state, mounts Shell + page content.
// Data layer: live Cloudflare Worker API (window.api).

const { useState: useStateA, useEffect: useEffectA } = React;

const App = () => {
  const [apps, setApps]     = useStateA({});
  const [loading, setLoading] = useStateA(true);
  const [route, setRoute]   = useStateA({ page: 'dashboard' });
  const [t, setTweak]       = window.useTweaks(window.TWEAK_DEFAULTS);

  // Initial load from worker
  useEffectA(() => {
    refreshApps();
  }, []);

  async function refreshApps() {
    setLoading(true);
    try {
      const { apps: a } = await window.api('/api/config');
      setApps(a || {});
    } catch (e) {
      if (e.status === 401) {
        window.toast?.('Session expired', 'error');
        window.SESSION.clear();
        setTimeout(() => location.reload(), 800);
        return;
      }
      window.toast?.('Load failed: ' + e.message, 'error');
    }
    setLoading(false);
  }

  // Tweak panel: apply via CSS vars
  useEffectA(() => {
    const root = document.documentElement;
    const hex = t.accent || '#00d084';
    root.style.setProperty('--accent', hex);
    root.style.setProperty('--accent-dim', hex + '24');
    root.style.setProperty('--accent-line', hex + '52');
    document.body.classList.toggle('no-backdrop', !t.showBackdrop);
  }, [t.accent, t.showBackdrop]);

  const navigate = (r) => {
    setRoute(r);
    setTimeout(() => {
      const ws = document.querySelector('.workspace');
      if (ws) ws.scrollTo({ top: 0, behavior: 'instant' });
    }, 0);
  };

  // Save (PUT) an app to the worker KV
  async function saveApp(draft) {
    const id = draft.id || (draft.type === 'pwa' ? 'pwa.' : 'app.') + window.slugify(draft.name);
    const body = stripDraftMeta({ ...draft, id });
    try {
      const { app } = await window.api(`/api/config/${encodeURIComponent(id)}`, { method: 'PUT', body });
      setApps(prev => ({ ...prev, [id]: app }));
      return app;
    } catch (e) {
      window.toast?.('Save failed: ' + (e.details?.details?.join?.(', ') || e.message), 'error');
      throw e;
    }
  }

  function stripDraftMeta(d) {
    const out = { ...d };
    delete out._editing;
    delete out._step;
    return out;
  }

  const onSaveDraft = async (draft) => {
    try {
      const saved = await saveApp(draft);
      window.toast(`Saved — ${saved.name}`, 'success');
    } catch {}
  };

  const onLaunch = async (draft) => {
    try {
      const launched = await saveApp({ ...draft, enabled: true, status: 'live' });
      window.toast(`🚀 ${launched.name} is live — routing in ~60s`, 'success');
      navigate({ page: 'app', appId: launched.id });
    } catch {}
  };

  const onDelete = async (app) => {
    if (!confirm(`Delete "${app.name}"? KV record removed.`)) return;
    try {
      await window.api(`/api/config/${encodeURIComponent(app.id)}`, { method: 'DELETE' });
      setApps(prev => { const n = { ...prev }; delete n[app.id]; return n; });
      window.toast(`Deleted ${app.name}`, 'success');
      navigate({ page: 'dashboard' });
    } catch (e) {
      window.toast?.('Delete failed: ' + e.message, 'error');
    }
  };

  // Toggle / inline update from AppDetail
  const onUpdate = async (next) => {
    try {
      const { app } = await window.api(`/api/config/${encodeURIComponent(next.id)}`, {
        method: 'PUT',
        body: stripDraftMeta(next),
      });
      setApps(prev => ({ ...prev, [app.id]: app }));
      if (next.enabled !== apps[next.id]?.enabled) {
        window.toast(`${app.name}: ${app.enabled ? 'LIVE' : 'OFF'} — routing in ~60s`, 'success');
      }
    } catch (e) {
      window.toast?.('Update failed: ' + e.message, 'error');
    }
  };

  const onSeed = async () => {
    try {
      const r = await window.api('/api/seed', { method: 'POST' });
      if (r.seeded) {
        window.toast(`Imported ${r.apps.length} apps`, 'success');
        await refreshApps();
      } else {
        window.toast(r.reason || 'Already seeded', 'error');
      }
    } catch (e) {
      window.toast?.('Seed failed: ' + e.message, 'error');
    }
  };

  // Breadcrumb
  const crumbs = (() => {
    if (route.page === 'dashboard') return [{ label: 'Dashboard' }];
    if (route.page === 'create')    return [{ label: 'Dashboard', onClick: () => navigate({ page: 'dashboard' }) }, { label: 'Create new app' }];
    if (route.page === 'edit')      return [{ label: 'Dashboard', onClick: () => navigate({ page: 'dashboard' }) }, { label: apps[route.appId]?.name || 'App', onClick: () => navigate({ page: 'app', appId: route.appId }) }, { label: 'Edit' }];
    if (route.page === 'app')       return [{ label: 'Dashboard', onClick: () => navigate({ page: 'dashboard' }) }, { label: apps[route.appId]?.name || 'App' }];
    return [{ label: route.page }];
  })();

  // Render
  let body;
  if (loading) {
    body = <LoadingState />;
  } else if (route.page === 'dashboard') {
    body = <window.Dashboard apps={apps} onRoute={navigate} onRefresh={refreshApps} onSeed={onSeed} />;
  } else if (route.page === 'create') {
    body = <window.Flow
      initialDraft={window.EMPTY_DRAFT()}
      onCancel={() => navigate({ page: 'dashboard' })}
      onSave={onSaveDraft}
      onLaunch={onLaunch}
    />;
  } else if (route.page === 'edit') {
    const app = apps[route.appId];
    body = app ? <window.Flow
      initialDraft={{ ...window.EMPTY_DRAFT(), ...app, _editing: true }}
      onCancel={() => navigate({ page: 'app', appId: route.appId })}
      onSave={onSaveDraft}
      onLaunch={onLaunch}
    /> : <NotFound />;
  } else if (route.page === 'app') {
    const app = apps[route.appId];
    body = app ? <window.AppDetail app={app} apps={apps} onRoute={navigate} onUpdate={onUpdate} onDelete={onDelete} /> : <NotFound />;
  } else {
    body = <Placeholder name={route.page} />;
  }

  return (
    <>
      <div className="shell">
        <window.Sidebar route={route} onRoute={navigate} apps={apps} onLogout={handleLogout} />
        <div className="workspace">
          <window.TopBar crumbs={crumbs} />
          {body}
        </div>
      </div>
      <window.ToastHost />
      <window.TweaksPanel title="Tweaks">
        <window.TweakSection label="Theme" />
        <window.TweakColor label="Accent" value={t.accent}
          options={['#00d084', '#66b3ff', '#b794f4', '#ffc36b', '#ff5a6e']}
          onChange={(v) => setTweak('accent', v)} />
        <window.TweakToggle label="Dot grid backdrop" value={t.showBackdrop}
          onChange={(v) => setTweak('showBackdrop', v)} />
      </window.TweaksPanel>
    </>
  );
};

function handleLogout() {
  window.SESSION.clear();
  location.reload();
}

const LoadingState = () => (
  <div className="page">
    <div className="empty">
      <h3>Loading…</h3>
      <p>Fetching your apps from the worker.</p>
    </div>
  </div>
);

const NotFound = () => (
  <div className="page">
    <div className="empty">
      <h3>Not found</h3>
      <p>This app doesn't exist anymore.</p>
    </div>
  </div>
);

const Placeholder = ({ name }) => (
  <div className="page">
    <div className="page-head"><div><h1 style={{ textTransform: 'capitalize' }}>{name}</h1><div className="desc">Coming soon.</div></div></div>
    <div className="panel" style={{ padding: 32, textAlign: 'center' }}>
      <div style={{ fontSize: 48, marginBottom: 12, opacity: 0.3 }}>🛠️</div>
      <div style={{ color: 'var(--muted)' }}>This page is in the next phase.</div>
    </div>
  </div>
);

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