/* contractor-books · main app */

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": ["#144D34", "#E89A2B", "#F4EFE6"],
  "density": "regular",
  "dark": false,
  "kpiStyle": "number",
  "showAlertBanner": true
}/*EDITMODE-END*/;

const PALETTES = {
  /* JSON.stringify keys — match the persisted format */
  '["#144D34","#E89A2B","#F4EFE6"]': {
    name: 'Cedar & cream',
    primary: '#144D34', primaryFg: '#FFFFFF', primaryTint: '#E1ECE5',
    accent: '#E89A2B', accentTint: '#FBEFD8',
    bg: '#F4EFE6', bg2: '#EDE6D8',
  },
  '["#1F2937","#F97316","#F8FAFC"]': {
    name: 'Slate & safety',
    primary: '#1F2937', primaryFg: '#FFFFFF', primaryTint: '#E2E8EE',
    accent: '#F97316', accentTint: '#FFE5D2',
    bg: '#F4F1EC', bg2: '#EBE7E0',
  },
  '["#1B3358","#D4A537","#F1ECE1"]': {
    name: 'Indigo & brass',
    primary: '#1B3358', primaryFg: '#FFFFFF', primaryTint: '#DCE3EE',
    accent: '#D4A537', accentTint: '#F5EBCC',
    bg: '#F1ECE1', bg2: '#E9E2D2',
  },
  '["#3B2A20","#C45A2C","#F7F2E8"]': {
    name: 'Walnut & clay',
    primary: '#3B2A20', primaryFg: '#FFFFFF', primaryTint: '#E8E0D7',
    accent: '#C45A2C', accentTint: '#F4DBCB',
    bg: '#F7F2E8', bg2: '#EFE7D6',
  },
};

const PALETTE_OPTIONS = Object.keys(PALETTES).map((k) => JSON.parse(k));

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [page, setPage] = React.useState('dashboard');
  const [period, setPeriod] = React.useState('mtd');
  const [openInvoice, setOpenInvoice] = React.useState(null);
  const [toasts, setToasts] = React.useState([]);
  const [bannerOn, setBannerOn] = React.useState(true);

  /* Apply tweak-driven CSS variables on root */
  React.useEffect(() => {
    const root = document.documentElement;
    const key = JSON.stringify(t.palette).toLowerCase();
    const found = Object.entries(PALETTES).find(([k]) => k.toLowerCase() === key);
    const p = found ? found[1] : Object.values(PALETTES)[0];
    if (!t.dark) {
      root.style.setProperty('--cb-primary', p.primary);
      root.style.setProperty('--cb-primary-fg', p.primaryFg);
      root.style.setProperty('--cb-primary-tint', p.primaryTint);
      root.style.setProperty('--cb-accent', p.accent);
      root.style.setProperty('--cb-accent-tint', p.accentTint);
      root.style.setProperty('--cb-bg', p.bg);
      root.style.setProperty('--cb-bg-2', p.bg2);
    } else {
      /* Let dark theme defaults from CSS reign, but keep accent hue */
      ['--cb-primary','--cb-primary-fg','--cb-primary-tint',
       '--cb-accent','--cb-accent-tint','--cb-bg','--cb-bg-2'].forEach((v) =>
        root.style.removeProperty(v));
    }
    root.dataset.theme = t.dark ? 'dark' : 'light';
    root.dataset.density = t.density;
  }, [t]);

  /* Refetch live data when the period filter changes (skip the initial mount —
     boot.jsx already loaded MTD). */
  const [, forceUpdate] = React.useReducer((x) => x + 1, 0);
  const firstPeriod = React.useRef(true);
  React.useEffect(() => {
    if (firstPeriod.current) { firstPeriod.current = false; return; }
    let alive = true;
    if (window.__CB_LOAD_DASHBOARD) {
      window.__CB_LOAD_DASHBOARD(period)
        .then(() => { if (alive) forceUpdate(); })
        .catch(() => {});
    }
    return () => { alive = false; };
  }, [period]);

  const pushToast = React.useCallback((t) => {
    const id = Math.random().toString(36).slice(2);
    setToasts((ts) => [...ts, { ...t, id }]);
    setTimeout(() => setToasts((ts) => ts.filter((x) => x.id !== id)), 4200);
  }, []);
  const dismissToast = (id) => setToasts((ts) => ts.filter((x) => x.id !== id));

  const alertCount = CB.invoices.filter((i) => i.status === 'overdue').length;

  const pageLabel = {
    dashboard: 'Dashboard', invoices: 'Invoices', jobs: 'Jobs',
    expenses: 'Expenses', clients: 'Clients', reports: 'Reports',
    tax: 'Tax center', documents: 'Documents', settings: 'Settings',
  };

  return (
    <div className="cb-app">
      <Sidebar active={page} onNavigate={setPage} />
      <main className="cb-main">
        <Topbar period={period} setPeriod={setPeriod}
                alertCount={alertCount}
                onOpenAlerts={() => pushToast({
                  kind: 'success', icon: 'bell',
                  title: `${alertCount} invoices overdue`,
                  body: `Total $24,890 outstanding — review below.`,
                })} />

        {page === 'dashboard' && (
          <DashboardPage
            t={t}
            bannerOn={bannerOn && t.showAlertBanner}
            onDismissBanner={() => setBannerOn(false)}
            onOpenInvoice={setOpenInvoice}
            pushToast={pushToast}
          />
        )}
        {page === 'invoices' && <InvoicesPage onOpenInvoice={setOpenInvoice} />}
        {page === 'jobs' && <JobsPage />}
        {page === 'expenses' && <ExpensesPage />}
        {page === 'clients' && <ClientsPage />}
        {page === 'tax' && <TaxCenterPage />}
        {page === 'reports' && <ReportsPage />}
        {page === 'documents' && <DocumentsPage pushToast={pushToast} />}
        {page === 'settings' && <SettingsPage />}
      </main>

      <InvoiceDrawer
        invoice={openInvoice}
        onClose={() => setOpenInvoice(null)}
        onToast={pushToast}
      />
      <Toaster toasts={toasts} onDismiss={dismissToast} />

      <TweaksPanel>
        <TweakSection label="Theme">
          <TweakColor label="Palette" value={t.palette} options={PALETTE_OPTIONS}
                      onChange={(v) => setTweak('palette', v)} />
          <TweakToggle label="Dark mode" value={t.dark}
                       onChange={(v) => setTweak('dark', v)} />
        </TweakSection>
        <TweakSection label="Layout">
          <TweakRadio label="Density" value={t.density}
                      options={['compact', 'regular', 'comfy']}
                      onChange={(v) => setTweak('density', v)} />
          <TweakRadio label="KPI cards" value={t.kpiStyle}
                      options={[{ value: 'number', label: 'Number' },
                                { value: 'chart',  label: 'Chart' }]}
                      onChange={(v) => setTweak('kpiStyle', v)} />
        </TweakSection>
        <TweakSection label="Content">
          <TweakToggle label="Alert banner" value={t.showAlertBanner}
                       onChange={(v) => setTweak('showAlertBanner', v)} />
        </TweakSection>
      </TweaksPanel>
    </div>
  );
}

/* ── Pages ─────────────────────────────────────────────────────────────── */

function DashboardPage({ t, bannerOn, onDismissBanner, onOpenInvoice, pushToast }) {
  const now = new Date();
  const hour = now.getHours();
  const greet = hour < 12 ? 'morning' : hour < 18 ? 'afternoon' : 'evening';
  const firstName = ((CB.company && CB.company.owner) || '').split(' ')[0] || 'there';
  const todayLabel = now.toLocaleDateString('en-US', { month: 'long', day: 'numeric' });

  /* Overdue summary derived from live invoices. */
  const overdue = (CB.invoices || []).filter((i) => i.status === 'overdue');
  const overdueSum = overdue.reduce((s, i) => s + i.amount, 0);
  const oldest = overdue.slice().sort((a, b) => CB.daysAgo(b.due) - CB.daysAgo(a.due))[0];

  return (
    <div className="cb-page" data-screen-label="01 Dashboard">
      <header className="cb-page-head">
        <div>
          <h1 className="cb-page-greet">Good {greet}, <em>{firstName}</em>.</h1>
          <p className="cb-page-sub">
            Here's how {CB.company.name} is doing — books current as of {todayLabel}.
          </p>
        </div>
        <div className="cb-page-head-right">
          <button type="button" className="cb-btn cb-btn-ghost">
            <IconDownload size={14} /> Export PDF
          </button>
          <button type="button" className="cb-btn cb-btn-primary">
            <IconPlus size={14} /> New invoice
          </button>
        </div>
      </header>

      {bannerOn && overdue.length > 0 && (
        <div className="cb-banner">
          <span className="cb-banner-ico"><IconAlert size={18} /></span>
          <div className="cb-banner-body">
            <b>{overdue.length} {overdue.length === 1 ? 'invoice is' : 'invoices are'} overdue, totaling {CB.fmtMoney(overdueSum)}</b>
            <span>{oldest ? `${oldest.client} has been unpaid for ${CB.daysAgo(oldest.due)} days. Send a reminder?` : 'Send a reminder?'}</span>
          </div>
          <div className="cb-banner-actions">
            <button type="button" className="cb-btn cb-btn-ghost" onClick={onDismissBanner}>Dismiss</button>
            <button type="button" className="cb-btn cb-btn-primary"
                    onClick={() => pushToast({
                      kind: 'success', icon: 'send',
                      title: '3 reminders sent', body: 'Polite emails sent to overdue clients.',
                    })}>
              <IconSend size={14} /> Send all reminders
            </button>
          </div>
        </div>
      )}

      <KpiRow cardStyle={t.kpiStyle} />
      <SecondaryKpiStrip />

      <div className="cb-grid-2-1">
        <CashFlowChart />
        <TaxWidget />
      </div>

      <div className="cb-grid-1-1">
        <RevExpChart />
        <JobsPanel />
      </div>

      <InvoicesPanel onOpen={onOpenInvoice} />

      <TransactionsPanel />
    </div>
  );
}

function InvoicesPage({ onOpenInvoice }) {
  return (
    <div className="cb-page" data-screen-label="02 Invoices">
      <header className="cb-page-head">
        <div>
          <h1 className="cb-page-greet">Invoices</h1>
          <p className="cb-page-sub">All open and recently-paid invoices across every job.</p>
        </div>
      </header>
      <InvoicesPanel onOpen={onOpenInvoice} />
    </div>
  );
}

function JobsPage() {
  return (
    <div className="cb-page" data-screen-label="03 Jobs">
      <header className="cb-page-head">
        <div>
          <h1 className="cb-page-greet">Jobs</h1>
          <p className="cb-page-sub">Active projects, budgets, and burn.</p>
        </div>
        <div className="cb-page-head-right">
          <button type="button" className="cb-btn cb-btn-primary">
            <IconPlus size={14} /> New job
          </button>
        </div>
      </header>
      <JobsPanel />
    </div>
  );
}

function PlaceholderPage({ label }) {
  return (
    <div className="cb-page">
      <div className="cb-placeholder">
        <div>
          <span className="cb-placeholder-ico"><IconHammer size={28} /></span>
          <h2>{label} — under construction</h2>
          <p>This page is part of the same prototype but hasn't been wired up yet. Use the sidebar to head back to the Dashboard.</p>
        </div>
      </div>
    </div>
  );
}

/* Rendering is owned by src/boot.jsx (auth gate + live data fetch). Expose App. */
Object.assign(window, { App });
