// ClientDashboardApp — top-level router + shell.
// On boot we resolve the client slug from ?c= and load its data
// (live from the Worker, or demo fallback). The loaded record reshapes
// window.JOY_MOVE so the rest of the UI stays untouched.

function ClientDashboardApp() {
  const t = useTweaks();
  const params = window.getPortalParams();
  const [loaded, setLoaded] = React.useState(false);
  const [loadError, setLoadError] = React.useState(null);
  const [source, setSource] = React.useState('demo');

  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const data = await window.Portal.loadClient();
        if (cancelled) return;
        // Reshape: the existing UI reads from window.JOY_MOVE; assign there.
        window.JOY_MOVE = {
          brand: data.brand,
          plans: { [data.plan.tier]: data.plan, ...(window.JOY_MOVE && window.JOY_MOVE.plans) },
          cycle: data.cycle,
          siteHealth: data.siteHealth || (window.JOY_MOVE && window.JOY_MOVE.siteHealth),
          requests: data.requests || [],
          requestCategories: data.requestCategories || [],
          activity: data.activity || [],
          roadmap: data.roadmap || [],
          resources: data.resources || [],
          invoices: data.invoices || [],
          messageThreads: data.messageThreads || [],
          messages: data.messages || [],
        };
        // Per-client branding override — if the client record carries an
        // accent color, set it as the live tweak (unless user has overridden).
        if (data.brand && data.brand.accent && !localStorage.getItem('somAccentTouched')) {
          window.applyTweaks({ accent: data.brand.accent });
        }
        if (data.plan && data.plan.tier && !localStorage.getItem('somTierTouched')) {
          window.applyTweaks({ tier: data.plan.tier });
        }
        setSource(data._source || 'demo');
        setLoaded(true);
      } catch (e) {
        setLoadError(e.message);
        setLoaded(true);
      }
    })();
    return () => { cancelled = true; };
  }, []);

  const pal = buildPal(t);

  if (!loaded) {
    return <BootScreen pal={pal} />;
  }
  if (loadError) {
    return <ErrorScreen pal={pal} message={loadError} />;
  }

  return <DashboardShell pal={pal} source={source} params={params} />;
}

function BootScreen({ pal }) {
  return (
    <div style={{ position: 'fixed', inset: 0, display: 'grid', placeItems: 'center', background: pal.bg, color: pal.muted, fontFamily: "'Plus Jakarta Sans', sans-serif" }}>
      <div style={{ textAlign: 'center' }}>
        <div style={{ fontFamily: "'Playfair Display', serif", fontSize: 28, fontWeight: 700, color: pal.textStrong, fontStyle: 'italic', marginBottom: 12 }}>State of Motion</div>
        <div style={{ fontSize: 13, letterSpacing: '0.1em', textTransform: 'uppercase', color: pal.muted }}>Loading your portal…</div>
      </div>
    </div>
  );
}

function ErrorScreen({ pal, message }) {
  return (
    <div style={{ position: 'fixed', inset: 0, display: 'grid', placeItems: 'center', background: pal.bg, color: pal.text, fontFamily: "'Plus Jakarta Sans', sans-serif", padding: 32 }}>
      <div style={{ maxWidth: 420, textAlign: 'center' }}>
        <div style={{ fontFamily: "'Playfair Display', serif", fontSize: 32, fontWeight: 700, color: pal.textStrong, marginBottom: 14 }}>Hmm — that's odd.</div>
        <div style={{ fontSize: 14, color: pal.muted, lineHeight: 1.6, marginBottom: 18 }}>We couldn't load your portal. This is usually a config issue on our end. Drop us a line at <a href="mailto:hello@thestateofmotion.com" style={{ color: pal.accent }}>hello@thestateofmotion.com</a>.</div>
        <div style={{ fontSize: 11, fontFamily: "'JetBrains Mono', monospace", color: pal.dim, padding: 10, background: pal.warm, borderRadius: 6, border: `1px solid ${pal.border}` }}>{message}</div>
      </div>
    </div>
  );
}

function DashboardShell({ pal, source, params }) {
  const jm = window.JOY_MOVE;

  // Persist nav in localStorage for refresh-friendly dev.
  const initialView = params.view === 'admin' ? 'admin' : (localStorage.getItem('somView') || 'client');
  const [view, setView] = React.useState(initialView);
  const [nav, setNav] = React.useState(() => localStorage.getItem('somNav') || 'overview');
  const [requestId, setRequestId] = React.useState(null);
  const [threadId, setThreadId] = React.useState(null);
  const [newReqOpen, setNewReqOpen] = React.useState(false);

  React.useEffect(() => { localStorage.setItem('somView', view); }, [view]);
  React.useEffect(() => { localStorage.setItem('somNav', nav); }, [nav]);

  const user = view === 'admin'
    ? { name: "Mara Castillo", initials: "MC" }
    : (() => {
        const c = (jm.brand && jm.brand.contact) || 'Client';
        const parts = c.split(/\s+/).filter(Boolean);
        const initials = (parts[0]?.[0] || '?') + (parts[1]?.[0] || '');
        return { name: c, initials: initials.toUpperCase() };
      })();

  // Navigation helpers passed down to pages
  const go = {
    to: (tab) => { setNav(tab); setRequestId(null); setThreadId(null); },
    request: (id) => { setNav('requests'); setRequestId(id); },
    thread: (id) => { setNav('messages'); setThreadId(id); },
    newRequest: () => setNewReqOpen(true),
    closeNewRequest: () => setNewReqOpen(false),
  };

  let body = null;

  if (view === 'admin') {
    body = <AdminRoster pal={pal} onOpenClient={(slug) => {
      // Reload so the loader picks up the new client; this keeps the
      // single-source-of-truth model where the URL fully determines state.
      const url = new URL(window.location.href);
      if (slug) url.searchParams.set('c', slug);
      url.searchParams.delete('view');
      localStorage.setItem('somView', 'client');
      localStorage.setItem('somNav', 'overview');
      window.location.href = url.toString();
    }} />;
  } else if (nav === 'overview') {
    body = <OverviewTab pal={pal} go={go} />;
  } else if (nav === 'requests') {
    body = requestId
      ? <RequestDetail pal={pal} go={go} id={requestId} />
      : <RequestsTab pal={pal} go={go} />;
  } else if (nav === 'resources') {
    body = <ResourcesTab pal={pal} />;
  } else if (nav === 'activity') {
    body = <ActivityTab pal={pal} go={go} />;
  } else if (nav === 'messages') {
    body = <MessagesTab pal={pal} threadId={threadId} setThreadId={setThreadId} />;
  } else if (nav === 'billing') {
    body = <BillingTab pal={pal} />;
  }

  return (
    <>
      <AppShell pal={pal} nav={nav} setNav={go.to} onNewRequest={go.newRequest} jm={jm} view={view} setView={setView} user={user}>
        {body}
      </AppShell>
      {newReqOpen && <NewRequestModal pal={pal} onClose={go.closeNewRequest} />}
      {source === 'demo' && window.SOM_CONFIG.apiBase && <DemoBadge pal={pal} />}
      {!window.SOM_CONFIG.apiBase && <DevBadge pal={pal} />}
    </>
  );
}

function DemoBadge({ pal }) {
  return (
    <div style={{
      position: 'fixed', top: 14, left: '50%', transform: 'translateX(-50%)',
      zIndex: 200, padding: '6px 14px',
      background: 'rgba(231,181,107,0.18)', color: '#e7b56b',
      border: '1px solid rgba(231,181,107,0.35)', borderRadius: 999,
      fontSize: 11, fontWeight: 600, letterSpacing: '0.06em',
      fontFamily: "'JetBrains Mono', monospace",
    }}>FALLBACK · Airtable not reachable, showing demo data</div>
  );
}

function DevBadge({ pal }) {
  // Only shown when no apiBase is configured — keeps you honest while developing.
  // Bottom-left so it mirrors the Tweaks panel and doesn't collide with the TopBar wordmark.
  return (
    <div style={{
      position: 'fixed', bottom: 14, left: 14, zIndex: 200,
      padding: '5px 10px',
      background: 'rgba(78,205,196,0.14)', color: pal.accent,
      border: `1px solid rgba(78,205,196,0.3)`, borderRadius: 999,
      fontSize: 10, fontWeight: 600, letterSpacing: '0.08em',
      fontFamily: "'JetBrains Mono', monospace", textTransform: 'uppercase',
    }}>Demo · no backend configured</div>
  );
}

// Generic page container — padding, max-width, section header
function Page({ pal, kicker, title, sub, actions, children }) {
  return (
    <div style={{ padding: '40px 48px 80px', maxWidth: 1280, margin: '0 auto' }}>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: 34, flexWrap: 'wrap', gap: 20 }}>
        <div>
          {kicker && <Kicker pal={pal}>{kicker}</Kicker>}
          <Display pal={pal} size={44}>{title}</Display>
          {sub && <div style={{ color: pal.muted, marginTop: 10, fontSize: 15, fontWeight: 300, maxWidth: 580, lineHeight: 1.55 }}>{sub}</div>}
        </div>
        {actions && <div style={{ display: 'flex', gap: 10 }}>{actions}</div>}
      </div>
      {children}
    </div>
  );
}

window.ClientDashboardApp = ClientDashboardApp;
window.Page = Page;
