/* Admin data + content + settings views. */

/* ============================================================
   PREDICTIONS BROWSER (PII visible to admin only)
   ============================================================ */
function AdminPredictions({ ctx }) {
  const [q, setQ] = useState('');
  const [matchFilter, setMatchFilter] = useState('');
  const [outletFilter, setOutletFilter] = useState('');
  const [correctFilter, setCorrectFilter] = useState(''); // '', 'yes', 'no', 'pending'
  const [page, setPage] = useState(0);
  const pageSize = 12;

  // Live predictions from Supabase; falls back to demo data if API not configured
  const [livePredictions, setLivePredictions] = useState(null); // null = loading
  const [loadError, setLoadError] = useState('');

  useEffect(() => {
    fetch('/api/get-predictions', {
      headers: { 'x-admin-key': ctx.adminToken },
    })
      .then(r => r.json())
      .then(data => {
        if (data.predictions) {
          setLivePredictions(data.predictions);
        } else {
          setLoadError(data.error || 'Could not load predictions.');
          setLivePredictions(SAMPLE_PREDICTIONS); // fallback to demo
        }
      })
      .catch(() => {
        setLoadError('Network error — showing demo data.');
        setLivePredictions(SAMPLE_PREDICTIONS);
      });
  }, []);

  const allPredictions = livePredictions !== null ? livePredictions : SAMPLE_PREDICTIONS;

  const filtered = useMemo(() => {
    return allPredictions.filter(p => {
      if (q) {
        const Q = q.toLowerCase();
        if (!(p.customerName + ' ' + p.customerPhone + ' ' + p.billNumber).toLowerCase().includes(Q)) return false;
      }
      if (matchFilter && String(p.matchId) !== matchFilter) return false;
      if (outletFilter && p.outlet !== outletFilter) return false;
      if (correctFilter === 'yes' && p.isCorrect !== true) return false;
      if (correctFilter === 'no' && p.isCorrect !== false) return false;
      if (correctFilter === 'pending' && p.isCorrect !== null) return false;
      return true;
    });
  }, [q, matchFilter, outletFilter, correctFilter]);

  const pages = Math.max(1, Math.ceil(filtered.length / pageSize));
  const visible = filtered.slice(page * pageSize, (page + 1) * pageSize);

  return (
    <AdminSection
      title="Predictions"
      sub="Customer data only visible here. Audit, search, filter, and export."
      right={
        <AdminBtn kind="outline" icon="receipt" onClick={() => ctx.setToast({ message: `Exporting ${filtered.length} predictions to CSV…`, tone: 'info' })}>
          Export {filtered.length} rows
        </AdminBtn>
      }
    >
      <div style={{
        background: '#fff8f3', border: '1.5px solid var(--orange-100)',
        padding: '10px 14px', display: 'flex', alignItems: 'center', gap: 10, marginBottom: 14,
        fontSize: 12.5, color: 'var(--ink)',
      }}>
        <span style={{ width: 8, height: 8, background: 'var(--orange)', flexShrink: 0 }} />
        <span>This screen displays personal customer data (name, mobile, bill). It is never reachable from a public endpoint.</span>
      </div>

      {livePredictions === null && !loadError && (
        <div style={{ padding: '20px 0', color: 'var(--grey-500)', fontSize: 13.5 }}>
          Loading predictions…
        </div>
      )}
      {loadError && (
        <div style={{
          padding: '10px 14px', background: '#fee2e2', color: '#b91c1c',
          border: '1px solid #fecaca', fontSize: 13, marginBottom: 12,
        }}>
          ⚠ {loadError}
          {!loadError.includes('demo') && (
            <span style={{ display: 'block', marginTop: 4, fontSize: 12, color: '#7f1d1d' }}>
              Check SUPABASE_URL / SUPABASE_SERVICE_KEY in Vercel env vars.
            </span>
          )}
        </div>
      )}

      <Panel padding={0}>
        {/* Filters */}
        <div style={{ padding: '14px 18px', borderBottom: '1px solid var(--grey-200)', display: 'grid', gridTemplateColumns: 'minmax(180px, 1fr) repeat(3, minmax(140px, 200px))', gap: 12, alignItems: 'end' }} className="pred-filters">
          <div>
            <FormLabel>Search</FormLabel>
            <input value={q} onChange={(e) => { setQ(e.target.value); setPage(0); }} placeholder="Name, phone, bill…" style={inputStyle} />
          </div>
          <div>
            <FormLabel>Match</FormLabel>
            <select value={matchFilter} onChange={(e) => { setMatchFilter(e.target.value); setPage(0); }} style={inputStyle}>
              <option value="">All matches</option>
              {ctx.matchesState.map(m => <option key={m.id} value={m.id}>{m.teamA.name} vs {m.teamB.name}</option>)}
            </select>
          </div>
          <div>
            <FormLabel>Outlet</FormLabel>
            <select value={outletFilter} onChange={(e) => { setOutletFilter(e.target.value); setPage(0); }} style={inputStyle}>
              <option value="">All outlets</option>
              {ctx.outletsState.map(o => <option key={o.id} value={o.name}>{o.name}</option>)}
            </select>
          </div>
          <div>
            <FormLabel>Result</FormLabel>
            <select value={correctFilter} onChange={(e) => { setCorrectFilter(e.target.value); setPage(0); }} style={inputStyle}>
              <option value="">All</option>
              <option value="yes">Correct</option>
              <option value="no">Incorrect</option>
              <option value="pending">Pending</option>
            </select>
          </div>
        </div>

        {/* Table */}
        <div style={{ overflowX: 'auto' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', minWidth: 980 }}>
            <thead>
              <tr style={{ background: 'var(--grey-50)' }}>
                <Th>Customer</Th>
                <Th>Mobile</Th>
                <Th>Bill #</Th>
                <Th>Amount (MVR)</Th>
                <Th>Match · pick</Th>
                <Th>Result</Th>
                <Th align="right">Submitted</Th>
              </tr>
            </thead>
            <tbody>
              {visible.map(p => (
                <tr key={p.id} style={{ borderTop: '1px solid var(--grey-100)' }}>
                  <Td>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                      <div style={{
                        width: 28, height: 28, borderRadius: '50%',
                        background: 'var(--ink)', color: 'var(--orange)',
                        display: 'flex', alignItems: 'center', justifyContent: 'center',
                        fontSize: 11, fontWeight: 800, fontFamily: "'Archivo Black', sans-serif",
                      }}>
                        {p.customerName.slice(0, 1)}
                      </div>
                      <span style={{ fontWeight: 600, fontSize: 13.5 }}>{p.customerName}</span>
                    </div>
                  </Td>
                  <Td><span className="font-mono" style={{ fontSize: 12.5 }}>{p.customerPhone}</span></Td>
                  <Td><span className="font-mono" style={{ fontSize: 12.5 }}>{p.billNumber}</span></Td>
                  <Td><span className="font-mono" style={{ fontSize: 13, fontWeight: 700 }}>{p.amountMyr != null ? `MVR ${Number(p.amountMyr).toFixed(2)}` : '—'}</span></Td>
                  <Td>
                    <div style={{ fontSize: 12.5 }}>{p.matchLabel}</div>
                    <div style={{ fontSize: 11, color: 'var(--orange)', fontWeight: 700, letterSpacing: '0.04em', marginTop: 2 }}>
                      → {p.pick.toUpperCase()}
                    </div>
                  </Td>
                  <Td>
                    {p.isCorrect === true && <ResultPill tone="green">Correct</ResultPill>}
                    {p.isCorrect === false && <ResultPill tone="grey">Incorrect</ResultPill>}
                    {p.isCorrect === null && <ResultPill tone="ink">Pending</ResultPill>}
                  </Td>
                  <Td align="right">
                    <span style={{ fontSize: 12.5, color: 'var(--grey-600)' }}>{timeAgo(p.submittedAt)}</span>
                  </Td>
                </tr>
              ))}
              {visible.length === 0 && (
                <tr><td colSpan="7" style={{ padding: 32, textAlign: 'center', color: 'var(--grey-500)' }}>No predictions match those filters.</td></tr>
              )}
            </tbody>
          </table>
        </div>

        {/* Pagination */}
        <div style={{
          padding: '12px 18px', borderTop: '1px solid var(--grey-200)',
          display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 10,
        }}>
          <div style={{ fontSize: 12.5, color: 'var(--grey-600)' }}>
            Showing {filtered.length === 0 ? 0 : page * pageSize + 1}–{Math.min((page + 1) * pageSize, filtered.length)} of {filtered.length}
          </div>
          <div style={{ display: 'flex', gap: 6 }}>
            <AdminBtn kind="ghost" disabled={page === 0} onClick={() => setPage(p => p - 1)}>← Prev</AdminBtn>
            <div style={{ display: 'flex', alignItems: 'center', padding: '0 10px', fontSize: 12.5, color: 'var(--grey-700)' }}>
              Page {page + 1} / {pages}
            </div>
            <AdminBtn kind="ghost" disabled={page + 1 >= pages} onClick={() => setPage(p => p + 1)}>Next →</AdminBtn>
          </div>
        </div>
      </Panel>

      <style>{`
        @media (max-width: 900px) {
          .pred-filters { grid-template-columns: 1fr 1fr !important; }
        }
        @media (max-width: 540px) {
          .pred-filters { grid-template-columns: 1fr !important; }
        }
      `}</style>
    </AdminSection>
  );
}

function ResultPill({ tone, children }) {
  const palette = {
    green: { bg: 'var(--success-bg)', fg: '#0f5f2e', bd: 'var(--success)' },
    grey:  { bg: 'var(--grey-100)',   fg: 'var(--grey-700)', bd: 'var(--grey-300)' },
    ink:   { bg: 'var(--ink)',        fg: '#fff',            bd: 'var(--ink)' },
  }[tone];
  return (
    <span style={{
      display: 'inline-block', background: palette.bg, color: palette.fg,
      border: `1px solid ${palette.bd}`, padding: '3px 9px',
      fontSize: 10.5, fontWeight: 700, letterSpacing: '0.1em', textTransform: 'uppercase',
    }}>{children}</span>
  );
}

/* ============================================================
   OUTLETS MANAGER
   ============================================================ */
function AdminOutlets({ ctx }) {
  const [draft, setDraft] = useState({ id: null, name: '', code: '', address: '' });

  function startNew() { setDraft({ id: null, name: '', code: '', address: '' }); }
  function startEdit(o) { setDraft({ ...o }); }
  function save() {
    if (!draft.name || !draft.code) return;
    if (draft.id) {
      ctx.setOutletsState(s => s.map(o => o.id === draft.id ? { ...draft } : o));
      ctx.setToast({ message: `Outlet "${draft.name}" updated.`, tone: 'success' });
    } else {
      const id = Math.max(0, ...ctx.outletsState.map(o => o.id)) + 1;
      ctx.setOutletsState(s => [...s, { ...draft, id }]);
      ctx.setToast({ message: `Outlet "${draft.name}" added.`, tone: 'success' });
    }
    startNew();
  }
  function remove(id) {
    if (!confirm('Delete this outlet? Predictions tied to it will keep their reference.')) return;
    ctx.setOutletsState(s => s.filter(o => o.id !== id));
    ctx.setToast({ message: 'Outlet removed.', tone: 'success' });
  }

  return (
    <AdminSection
      title="Outlets"
      sub="The four physical SunFront outlets in Malé. These appear in the Predict page outlet dropdown."
      right={<AdminBtn kind="primary" icon="pin" onClick={startNew}>Add new outlet</AdminBtn>}
    >
      <div className="admin-2col" style={{ display: 'grid', gridTemplateColumns: '1fr 360px', gap: 18 }}>
        {/* List */}
        <div style={{ display: 'grid', gap: 14 }}>
          {ctx.outletsState.map(o => {
            const predCount = SAMPLE_PREDICTIONS.filter(p => p.outlet === o.name).length;
            return (
              <div key={o.id} style={{
                background: '#fff', border: '1.5px solid var(--grey-200)',
                padding: '16px 18px',
                display: 'flex', alignItems: 'center', gap: 14, flexWrap: 'wrap',
              }}>
                <div style={{
                  width: 48, height: 48, background: 'var(--orange)', color: '#fff',
                  display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
                }}>
                  <Icon name="pin" size={22} />
                </div>
                <div style={{ flex: 1, minWidth: 200 }}>
                  <div className="font-display" style={{ fontSize: 18 }}>{o.name}</div>
                  <div style={{ fontSize: 12.5, color: 'var(--grey-600)', marginTop: 2 }}>
                    <span className="font-mono">{o.code}</span> · {o.address}
                  </div>
                </div>
                <div style={{ textAlign: 'right', minWidth: 120 }}>
                  <div className="font-display" style={{ fontSize: 22, lineHeight: 1 }}>{predCount.toLocaleString()}</div>
                  <div style={{ fontSize: 10.5, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--grey-500)', fontWeight: 700 }}>Predictions</div>
                </div>
                <div style={{ display: 'flex', gap: 6 }}>
                  <IconBtn icon="message" title="Edit" onClick={() => startEdit(o)} />
                  <IconBtn icon="bolt" title="Delete" tone="danger" onClick={() => remove(o.id)} />
                </div>
              </div>
            );
          })}
        </div>

        {/* Edit form */}
        <Panel title={draft.id ? 'Edit outlet' : 'Add new outlet'}>
          <div style={{ display: 'grid', gap: 14 }}>
            <div>
              <FormLabel>Display name</FormLabel>
              <input value={draft.name} onChange={(e) => setDraft({ ...draft, name: e.target.value })} placeholder="e.g. LIVIN" style={inputStyle} />
            </div>
            <div>
              <FormLabel>Code</FormLabel>
              <input value={draft.code} onChange={(e) => setDraft({ ...draft, code: e.target.value.toUpperCase() })} placeholder="LIVIN" className="font-mono input-upper" style={{ ...inputStyle, fontFamily: "'JetBrains Mono', monospace" }} />
            </div>
            <div>
              <FormLabel>Address</FormLabel>
              <input value={draft.address} onChange={(e) => setDraft({ ...draft, address: e.target.value })} placeholder="Building, street" style={inputStyle} />
            </div>
            <div style={{ display: 'flex', gap: 10 }}>
              <AdminBtn kind="primary" icon="check" onClick={save}>{draft.id ? 'Save changes' : 'Add outlet'}</AdminBtn>
              {draft.id && <AdminBtn kind="ghost" onClick={startNew}>Cancel</AdminBtn>}
            </div>
          </div>
        </Panel>
      </div>

      <style>{`
        @media (max-width: 900px) {
          .admin-2col { grid-template-columns: 1fr !important; }
        }
      `}</style>
    </AdminSection>
  );
}

/* ============================================================
   CONTENT EDITOR  (homepage text + images)
   ============================================================ */
function AdminContent({ ctx }) {
  const [draft, setDraft] = useState(() => ({ ...ctx.contentState }));
  const dirty = JSON.stringify(draft) !== JSON.stringify(ctx.contentState);

  const update = (path, value) => {
    const parts = path.split('.');
    setDraft(d => {
      const n = { ...d };
      let cur = n;
      for (let i = 0; i < parts.length - 1; i++) {
        cur[parts[i]] = { ...cur[parts[i]] };
        cur = cur[parts[i]];
      }
      cur[parts[parts.length - 1]] = value;
      return n;
    });
  };

  function save() {
    ctx.setContentState(draft);
    ctx.setToast({ message: 'Site content saved. The public site picks this up on next load.', tone: 'success' });
  }
  function discard() {
    setDraft({ ...ctx.contentState });
    ctx.setToast({ message: 'Changes discarded.', tone: 'info' });
  }
  function resetDefaults() {
    if (!confirm('Reset all content to factory defaults? Your edits will be lost.')) return;
    setDraft({ ...SITE_CONTENT_DEFAULTS });
    ctx.setContentState({ ...SITE_CONTENT_DEFAULTS });
    ctx.setToast({ message: 'Content reset to defaults.', tone: 'info' });
  }

  return (
    <AdminSection
      title="Content & images"
      sub="Edit every word and image on the public site. Changes here update Home, the ticket card, and footer."
      right={
        <div style={{ display: 'flex', gap: 8 }}>
          <AdminBtn kind="ghost" onClick={resetDefaults}>Reset defaults</AdminBtn>
          <AdminBtn kind="primary" icon="check" disabled={!dirty} onClick={save}>Publish changes</AdminBtn>
        </div>
      }
    >
      <div className="admin-2col" style={{ display: 'grid', gridTemplateColumns: '1.1fr 0.9fr', gap: 18 }}>
        {/* Editors */}
        <div style={{ display: 'grid', gap: 14 }}>
          <ContentSection title="Hero headline">
            <FieldRow label="Eyebrow badge"
              value={draft.hero.eyebrow}
              onChange={(v) => update('hero.eyebrow', v)} />
            <FieldRow label="Headline"
              value={draft.hero.headline}
              onChange={(v) => update('hero.headline', v)}
              textarea />
            <FieldRow label="Highlighted phrase"
              value={draft.hero.headlineHighlight}
              onChange={(v) => update('hero.headlineHighlight', v)}
              hint="Must be a substring of the headline — gets the orange marker." />
            <FieldRow label="Sub-headline"
              value={draft.hero.sub}
              onChange={(v) => update('hero.sub', v)}
              textarea />
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
              <FieldRow label="Primary CTA"
                value={draft.hero.ctaPrimary}
                onChange={(v) => update('hero.ctaPrimary', v)} />
              <FieldRow label="Secondary CTA"
                value={draft.hero.ctaSecondary}
                onChange={(v) => update('hero.ctaSecondary', v)} />
            </div>
          </ContentSection>

          <ContentSection title="Ticket card">
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 120px', gap: 10 }}>
              <FieldRow label="Tournament name"
                value={draft.ticket.title}
                onChange={(v) => update('ticket.title', v)} />
              <FieldRow label="Year"
                value={draft.ticket.year}
                onChange={(v) => update('ticket.year', v)} />
            </div>
            <FieldRow label="Region"
              value={draft.ticket.region}
              onChange={(v) => update('ticket.region', v)} />
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
              <FieldRow label="Outlets count"
                value={draft.ticket.outlets}
                onChange={(v) => update('ticket.outlets', v)} />
              <FieldRow label="Matches count"
                value={draft.ticket.matches}
                onChange={(v) => update('ticket.matches', v)} />
            </div>
          </ContentSection>

          <ContentSection title="Logo & images">
            <ImageDropzone label="SunFront logo (replaces /public/sunfront-logo.jpg)" current="placeholder" onPick={() => ctx.setToast({ message: 'In production this writes to /public/sunfront-logo.jpg', tone: 'info' })} />
            <ImageDropzone label="Hero background (optional)" current={null} onPick={() => ctx.setToast({ message: 'Uploaded — saved to /public/hero-bg.jpg', tone: 'info' })} />
          </ContentSection>

          <ContentSection title="Brand chrome">
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
              <FieldRow label="Hotline number"
                value={draft.hotline}
                onChange={(v) => update('hotline', v)} mono />
              <FieldRow label="Region"
                value={draft.hotlineRegion}
                onChange={(v) => update('hotlineRegion', v)} />
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 100px', gap: 10 }}>
              <FieldRow label="Tagline"
                value={draft.tagline}
                onChange={(v) => update('tagline', v)} />
              <FieldRow label="Since"
                value={draft.since}
                onChange={(v) => update('since', v)} mono />
            </div>
            <FieldRow label="Footer links"
              value={draft.footerLinks}
              onChange={(v) => update('footerLinks', v)} mono />
            <FieldRow label="Footer legal"
              value={draft.footerLegal}
              onChange={(v) => update('footerLegal', v)}
              textarea />
          </ContentSection>
        </div>

        {/* Live preview panel */}
        <div style={{ display: 'grid', gap: 14, alignContent: 'start', position: 'sticky', top: 90 }}>
          <Panel title="Live preview" action={<span style={{ fontSize: 11, color: 'var(--grey-500)', letterSpacing: '0.08em', textTransform: 'uppercase' }}>Hero</span>}>
            <ContentPreview draft={draft} />
          </Panel>
          <Panel title="Ticket card preview">
            <TicketPreview draft={draft} />
          </Panel>
        </div>
      </div>

      <style>{`
        @media (max-width: 1100px) {
          .admin-2col { grid-template-columns: 1fr !important; }
        }
      `}</style>
    </AdminSection>
  );
}

function ContentSection({ title, children }) {
  const [open, setOpen] = useState(true);
  return (
    <div style={{ background: '#fff', border: '1.5px solid var(--grey-200)' }}>
      <button onClick={() => setOpen(o => !o)} style={{
        width: '100%', background: open ? 'var(--grey-50)' : '#fff', border: 'none',
        padding: '12px 18px', textAlign: 'left', cursor: 'pointer',
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        borderBottom: open ? '1px solid var(--grey-200)' : 'none',
      }}>
        <span className="font-display" style={{ fontSize: 15, letterSpacing: '-0.01em' }}>{title}</span>
        <span style={{ color: 'var(--grey-500)', fontSize: 12, transform: open ? 'rotate(180deg)' : 'rotate(0)', transition: 'transform 0.2s' }}>▼</span>
      </button>
      {open && <div style={{ padding: 18, display: 'grid', gap: 12 }}>{children}</div>}
    </div>
  );
}
function FieldRow({ label, value, onChange, textarea, hint, mono }) {
  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
        <FormLabel>{label}</FormLabel>
        {hint && <span style={{ fontSize: 11, color: 'var(--grey-500)' }}>{hint}</span>}
      </div>
      {textarea ? (
        <textarea value={value} onChange={(e) => onChange(e.target.value)} rows={3} style={{ ...inputStyle, resize: 'vertical', fontFamily: 'inherit' }} />
      ) : (
        <input value={value} onChange={(e) => onChange(e.target.value)}
          className={mono ? 'font-mono' : ''}
          style={{ ...inputStyle, fontFamily: mono ? "'JetBrains Mono', monospace" : 'inherit' }} />
      )}
    </div>
  );
}
function ImageDropzone({ label, current, onPick }) {
  return (
    <div>
      <FormLabel>{label}</FormLabel>
      <div onClick={onPick} style={{
        border: '2px dashed var(--grey-300)', padding: 18, background: 'var(--grey-50)',
        cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 14,
      }}>
        <div style={{
          width: 60, height: 60, background: current ? 'var(--ink)' : 'var(--grey-100)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          {current ? <SunFrontLogo height={26} onWhite={false} /> :
            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="var(--grey-400)" strokeWidth="2"><rect x="3" y="3" width="18" height="18"/><path d="M3 16l5-5 4 4 3-3 6 6"/><circle cx="9" cy="9" r="2"/></svg>}
        </div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 13.5, fontWeight: 600 }}>
            {current ? 'Current asset · click to replace' : 'Click or drag a file here'}
          </div>
          <div style={{ fontSize: 11.5, color: 'var(--grey-500)', marginTop: 2 }}>PNG / JPG · recommended ≤ 500 KB</div>
        </div>
        <span style={{
          background: 'var(--orange)', color: '#fff', padding: '7px 12px',
          fontSize: 11, fontWeight: 700, letterSpacing: '0.08em', textTransform: 'uppercase',
        }}>Upload</span>
      </div>
    </div>
  );
}

function ContentPreview({ draft }) {
  const hl = draft.hero.headlineHighlight;
  const parts = hl && draft.hero.headline.includes(hl)
    ? draft.hero.headline.split(hl)
    : [draft.hero.headline];
  return (
    <div style={{ background: '#fff', padding: 6 }}>
      <div className="skew-tag" style={{
        background: 'var(--ink)', color: '#fff', display: 'inline-flex', alignItems: 'center', gap: 8,
        padding: '6px 12px', fontSize: 10, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase',
      }}>
        <span className="skew-tag-inner" style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
          <span className="pulse-dot" style={{ width: 6, height: 6, background: 'var(--orange)', borderRadius: '50%' }} />
          {draft.hero.eyebrow}
        </span>
      </div>
      <h2 className="font-display" style={{ fontSize: 24, lineHeight: 1, margin: '14px 0 10px', letterSpacing: '-0.02em' }}>
        {parts[0]}
        {parts.length > 1 && <>
          <span style={{ position: 'relative', whiteSpace: 'nowrap' }}>
            <span style={{ position: 'absolute', left: 0, right: 0, bottom: '8%', height: '38%', background: 'var(--orange)', opacity: 0.85, transform: 'skewX(-6deg)' }} />
            <span style={{ position: 'relative' }}>{hl}</span>
          </span>
          {parts[1]}
        </>}
      </h2>
      <p style={{ color: 'var(--grey-600)', fontSize: 12.5, lineHeight: 1.5, margin: 0 }}>{draft.hero.sub}</p>
      <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
        <span className="font-display" style={{ background: 'var(--orange)', color: '#fff', padding: '8px 14px', fontSize: 11, letterSpacing: '0.06em', textTransform: 'uppercase', borderRadius: 4, boxShadow: '0 2px 8px rgba(241,86,35,0.25)' }}>{draft.hero.ctaPrimary}</span>
        <span className="font-display" style={{ background: '#fff', color: 'var(--ink)', padding: '7px 13px', fontSize: 11, letterSpacing: '0.06em', textTransform: 'uppercase', border: '1.5px solid var(--ink)' }}>{draft.hero.ctaSecondary}</span>
      </div>
    </div>
  );
}

function TicketPreview({ draft }) {
  return (
    <div style={{ background: 'var(--grey-50)', padding: 14, display: 'flex', justifyContent: 'center' }}>
      <div style={{ background: '#fff', border: '1px solid var(--grey-200)', borderRadius: 8, boxShadow: '0 2px 12px rgba(17,6,24,0.08)', maxWidth: 240, width: '100%', overflow: 'hidden' }}>
        <div style={{ background: 'var(--ink)', color: '#fff', padding: '8px 14px', fontSize: 10, letterSpacing: '0.16em', textTransform: 'uppercase', fontWeight: 700 }}>
          <span style={{ color: 'var(--orange)' }}>Match day pass</span>
        </div>
        <div className="stripes-bg" style={{ height: 6 }} />
        <div style={{ padding: 14 }}>
          <div className="font-display" style={{ fontSize: 16, letterSpacing: '-0.01em' }}>
            {draft.ticket.title}<br />
            <span style={{ color: 'var(--orange)' }}>{draft.ticket.year}</span>
          </div>
          <div style={{ fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--grey-600)', marginTop: 6, fontWeight: 600 }}>{draft.ticket.region}</div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginTop: 10 }}>
            <div style={{ border: '1.5px solid var(--ink)', padding: '6px 8px' }}>
              <div style={{ fontSize: 9, letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--grey-600)', fontWeight: 700 }}>Outlets</div>
              <div className="font-display" style={{ fontSize: 18 }}>{draft.ticket.outlets}</div>
            </div>
            <div style={{ border: '1.5px solid var(--ink)', padding: '6px 8px' }}>
              <div style={{ fontSize: 9, letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--grey-600)', fontWeight: 700 }}>Matches</div>
              <div className="font-display" style={{ fontSize: 18 }}>{draft.ticket.matches}</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ============================================================
   SETTINGS
   ============================================================ */
function AdminSettings({ ctx }) {
  const [accentColor, setAccentColor] = useState('#ee5722');
  const [oldPw, setOldPw] = useState('');
  const [newPw, setNewPw] = useState('');
  const [newPw2, setNewPw2] = useState('');

  function changePassword() {
    if (!oldPw || !newPw) return;
    if (newPw !== newPw2) { ctx.setToast({ message: 'Passwords don\'t match.', tone: 'error' }); return; }
    if (newPw.length < 8) { ctx.setToast({ message: 'Password must be at least 8 characters.', tone: 'error' }); return; }
    ctx.setToast({ message: 'Password updated. Sign in again on other devices.', tone: 'success' });
    setOldPw(''); setNewPw(''); setNewPw2('');
  }
  function rotateSecret(which) {
    ctx.setToast({ message: `${which} rotated. Update your Vercel env var.`, tone: 'info' });
  }

  return (
    <AdminSection
      title="Settings"
      sub="Administrator account, brand, and infrastructure secrets."
    >
      <div className="admin-2col" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 18 }}>
        <Panel title="Admin password">
          <div style={{ display: 'grid', gap: 12 }}>
            <FieldRow label="Current password" value={oldPw} onChange={setOldPw} />
            <FieldRow label="New password" value={newPw} onChange={setNewPw} hint="At least 8 chars" />
            <FieldRow label="Confirm new password" value={newPw2} onChange={setNewPw2} />
            <div>
              <AdminBtn kind="primary" icon="check" onClick={changePassword}>Update password</AdminBtn>
            </div>
          </div>
        </Panel>

        <Panel title="Brand accent">
          <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
            <input type="color" value={accentColor} onChange={(e) => setAccentColor(e.target.value)}
              style={{ width: 56, height: 56, border: '1.5px solid var(--grey-300)', padding: 4, cursor: 'pointer' }} />
            <div style={{ flex: 1 }}>
              <FormLabel>Primary orange</FormLabel>
              <input value={accentColor} onChange={(e) => setAccentColor(e.target.value)} className="font-mono" style={{ ...inputStyle, fontFamily: "'JetBrains Mono', monospace" }} />
            </div>
          </div>
          <p style={{ fontSize: 12, color: 'var(--grey-500)', marginTop: 12, marginBottom: 0 }}>
            Pulled from the SunFront logo. Changing this re-themes buttons, accents, and the starburst echo across the public site.
          </p>
          <div style={{ marginTop: 12 }}>
            <AdminBtn kind="primary" icon="check" onClick={() => ctx.setToast({ message: 'Brand accent saved.', tone: 'success' })}>Apply theme</AdminBtn>
          </div>
        </Panel>

        <Panel title="Infrastructure secrets">
          <SecretRow label="Session signing secret" value="••••••••••••••••••••••••••••5f3a" onRotate={() => rotateSecret('SESSION_SECRET')} />
          <SecretRow label="Cron endpoint secret"   value="••••••••••••••••••••••••••••a82c" onRotate={() => rotateSecret('CRON_SECRET')} />
          <p style={{ fontSize: 12, color: 'var(--grey-500)', margin: '14px 0 0' }}>
            Rotating invalidates all admin sessions and the Vercel cron until you update env vars.
          </p>
        </Panel>

        <Panel title="Database & exports">
          <SettingRow label="Postgres host">
            <span className="font-mono" style={{ fontSize: 12 }}>ep-cool-rain-83.eu-west-2.aws.neon.tech</span>
          </SettingRow>
          <SettingRow label="Total predictions stored">
            <span className="font-display" style={{ fontSize: 18 }}><AnimatedCounter value={6842} /></span>
          </SettingRow>
          <SettingRow label="Last cron sync">
            <span style={{ fontSize: 12.5, color: 'var(--grey-600)' }}>{timeAgo(Date.now() - 1000 * 60 * 6)} · 1 transition</span>
          </SettingRow>
          <div style={{ marginTop: 14, display: 'flex', gap: 8, flexWrap: 'wrap' }}>
            <AdminBtn kind="outline" icon="receipt" onClick={() => ctx.setToast({ message: 'Full database export queued.', tone: 'info' })}>Export full DB</AdminBtn>
            <AdminBtn kind="ghost" onClick={() => ctx.setToast({ message: 'Cron synced.', tone: 'success' })}>Run cron now</AdminBtn>
          </div>
        </Panel>
      </div>

      <style>{`
        @media (max-width: 900px) {
          .admin-2col { grid-template-columns: 1fr !important; }
        }
      `}</style>
    </AdminSection>
  );
}

function SecretRow({ label, value, onRotate }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12,
      padding: '12px 0', borderTop: '1px solid var(--grey-100)',
    }}>
      <div style={{ minWidth: 0 }}>
        <div style={{ fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--grey-600)', fontWeight: 700 }}>{label}</div>
        <div className="font-mono" style={{ fontSize: 12.5, marginTop: 4, overflow: 'hidden', textOverflow: 'ellipsis' }}>{value}</div>
      </div>
      <AdminBtn kind="ghost" onClick={onRotate}>Rotate</AdminBtn>
    </div>
  );
}
function SettingRow({ label, children }) {
  return (
    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '8px 0', borderTop: '1px solid var(--grey-100)' }}>
      <span style={{ fontSize: 12.5, color: 'var(--grey-600)' }}>{label}</span>
      <span style={{ textAlign: 'right' }}>{children}</span>
    </div>
  );
}

Object.assign(window, {
  AdminPredictions, AdminOutlets, AdminContent, AdminSettings,
});
