// Admin Dashboard — basic structure
const { useState: useStateA } = React;

function AdminPage({ user, onNav }) {
  const [tab, setTab] = useStateA('apps');
  const isSuperadmin = user && user.role === 'superadmin';
  const tabs = [
    { value: 'apps',     label: 'Applications' },
    { value: 'posts',    label: 'Posts' },
    { value: 'amb',      label: 'Ambassadors' },
    { value: 'sprints',  label: 'Sprint Management' },
    ...(isSuperadmin ? [{ value: 'team', label: 'Team' }] : [])
  ];
  return (
    <main className="dash admin">
      <div className="container">
        <header className="dash-head">
          <div>
            <span className="kicker">Bloom · Internal</span>
            <h1 className="serif-h1">Admin</h1>
          </div>
          <div className="dash-head-right">
            <span className="pill purple">{isSuperadmin ? 'Superadmin' : 'Editor access'}</span>
          </div>
        </header>
        <Tabs items={tabs} value={tab} onChange={setTab}/>
        <div className="tab-panel">
          {tab === 'apps' && <AdminApps/>}
          {tab === 'posts' && <AdminPosts/>}
          {tab === 'amb' && <AdminAmbassadors/>}
          {tab === 'sprints' && <AdminSprints/>}
          {tab === 'team' && isSuperadmin && <AdminTeam/>}
        </div>
      </div>
    </main>
  );
}

// ─── Team management (superadmin only) ─────────────────────
function AdminTeam() {
  const [members, setMembers] = useStateA([]);
  const [newHandle, setNewHandle] = useStateA('');
  const [error, setError] = useStateA('');
  const [adding, setAdding] = useStateA(false);

  React.useEffect(() => {
    window._api.getAdminTeam().then(setMembers).catch(() => {});
  }, []);

  const addAdmin = () => {
    if (!newHandle.trim()) return;
    setAdding(true); setError('');
    window._api.addAdminTeam(newHandle.trim())
      .then(m => { setMembers([...members, m]); setNewHandle(''); })
      .catch(e => setError(e.message))
      .finally(() => setAdding(false));
  };

  const removeAdmin = async (id, name) => {
    const ok = await window.ui.confirm({
      title: `Remove admin access for ${name}?`,
      message: 'They will lose the admin role immediately. You can re-add them later.',
      danger: true,
      confirmLabel: 'Remove',
    });
    if (!ok) return;
    window._api.removeAdminTeam(id)
      .then(() => { setMembers(members.filter(m => m.id !== id)); window.ui.toast(`${name} removed.`, { kind: 'success' }); })
      .catch(e => window.ui.toast(e.message, { kind: 'error' }));
  };

  return (
    <section className="card">
      <header className="card-head row">
        <div>
          <h2 className="serif-h3">Admin Team</h2>
        </div>
        <span className="mono-count">{members.length}</span>
      </header>

      <div className="table-wrap sticky-head">
        <table className="data-table">
          <thead>
            <tr><th>Name</th><th>Twitter</th><th>Role</th><th>Added</th><th></th></tr>
          </thead>
          <tbody>
            {members.map(m => (
              <tr key={m.id}>
                <td><strong>{m.name}</strong></td>
                <td className="mono">@{m.handle}</td>
                <td>
                  <span className={`pill ${m.role === 'superadmin' ? 'purple' : ''}`} style={{fontSize:11,padding:'2px 10px'}}>
                    {m.role === 'superadmin' ? 'Superadmin' : 'Admin'}
                  </span>
                </td>
                <td className="mono">{fmtDate(m.joined)}</td>
                <td className="actions-cell">
                  {m.role !== 'superadmin' && (
                    <button className="btn btn-mini bad" onClick={() => removeAdmin(m.id, m.name)}>Remove</button>
                  )}
                </td>
              </tr>
            ))}
            {members.length === 0 && (
              <tr><td colSpan="5" className="empty">No team members yet.</td></tr>
            )}
          </tbody>
        </table>
      </div>

      <div style={{padding:'20px 24px',borderTop:'1px solid var(--line)',display:'flex',gap:10,alignItems:'center'}}>
        <input
          className="input"
          placeholder="Twitter handle (e.g. @username)"
          value={newHandle}
          onChange={(e) => setNewHandle(e.target.value)}
          onKeyDown={(e) => e.key === 'Enter' && addAdmin()}
          style={{flex:1, maxWidth:320}}
        />
        <button className="btn btn-primary" onClick={addAdmin} disabled={adding || !newHandle.trim()}>
          {adding ? 'Adding…' : 'Add Admin'}
        </button>
        {error && <span style={{color:'var(--red)',fontSize:13,fontFamily:'var(--mono)'}}>{error}</span>}
      </div>
    </section>
  );
}

function AdminApps() {
  const [rows, setRows] = useStateA(window.MOCK_APPLICATIONS || []);
  const [open, setOpen] = useStateA(null);

  // Fetch fresh on every mount so navigations don't show stale data.
  React.useEffect(() => {
    window._api.getAdminApplications()
      .then(d => { const list = Array.isArray(d) ? d : []; setRows(list); window.MOCK_APPLICATIONS = list; })
      .catch(() => {});
  }, []);

  const setStatus = (id, status) => {
    const row = rows.find(r => r.id === id);
    window._api.updateAdminApplication(id, { status, expectedUpdatedAt: row?.updated_at })
      .then(() => { setRows(rows.map(r => r.id === id ? { ...r, status } : r)); window.ui.toast(`Status set to ${status}.`, { kind: 'success' }); })
      .catch(err => window.ui.toast(err.message, { kind: 'error' }));
  };
  const removeApp = async (id, name) => {
    const ok = await window.ui.confirm({
      title: `Delete the application from ${name}?`,
      message: 'Their submitted answers will be wiped and they will be reset to "waiting". They can re-apply.',
      danger: true,
      confirmLabel: 'Delete',
    });
    if (!ok) return;
    window._api.deleteAdminApplication(id)
      .then(() => { setRows(rows.filter(r => r.id !== id)); if (open && open.id === id) setOpen(null); window.ui.toast(`Application from ${name} deleted.`, { kind: 'success' }); })
      .catch(err => window.ui.toast(err.message, { kind: 'error' }));
  };
  return (
    <section className="card">
      <header className="card-head row">
        <div>
          <h2 className="serif-h3">Applications</h2>
        </div>
        <div className="card-head-actions">
          <ExportCsvButton kind="applications"/>
          <span className="mono-count">{rows.length}</span>
        </div>
      </header>
      <div className="table-wrap sticky-head">
        <table className="data-table">
          <thead>
            <tr>
              <th>Name</th><th>Twitter</th><th>Tier</th><th>Date</th><th>Status</th><th></th>
            </tr>
          </thead>
          <tbody>
            {rows.map(r => (
              <tr key={r.id}>
                <td><button className="link" onClick={() => setOpen(r)}>{r.name}</button></td>
                <td className="mono">@{r.twitter}</td>
                <td><span className={`tier-mini ${r.tier}`}>{capitalize(r.tier)}</span></td>
                <td className="mono">{fmtDate(r.date)}</td>
                <td><AppStatusPill status={r.status}/></td>
                <td className="actions-cell">
                  <button className="btn btn-mini ok" onClick={() => setStatus(r.id, 'approved')}>Approve</button>
                  <button className="btn btn-mini bad" onClick={() => setStatus(r.id, 'rejected')}>Reject</button>
                  {r.status === 'rejected' && (
                    <button className="btn btn-mini ghost" onClick={() => setStatus(r.id, 'waiting')}>Reset to waiting</button>
                  )}
                  <button className="icon-btn" title="Delete application" onClick={() => removeApp(r.id, r.name)}>
                    <Icon name="trash" size={14}/>
                  </button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      {open && (
        <Modal open onClose={() => setOpen(null)}>
          <header className="modal-head">
            <div>
              <span className="mono-label">Application</span>
              <h3 className="serif-h2">{open.name}</h3>
              <p className="card-sub mono">@{open.twitter} · {fmtDate(open.date)}</p>
            </div>
            <button className="icon-btn" onClick={() => setOpen(null)}><Icon name="x" size={16}/></button>
          </header>
          <div className="modal-body">
            <ApplicationDetail row={open}/>
            <div className="modal-actions">
              <button className="btn btn-mini bad" onClick={() => removeApp(open.id, open.name)}>
                <Icon name="trash" size={14}/> Delete
              </button>
              <div style={{ flex: 1 }}/>
              {open.status === 'rejected' && (
                <button className="btn btn-ghost" onClick={() => { setStatus(open.id, 'waiting'); setOpen(null); }}>Reset to waiting</button>
              )}
              <button className="btn btn-ghost" onClick={() => { setStatus(open.id, 'rejected'); setOpen(null); }}>Reject</button>
              <button className="btn btn-primary" onClick={() => { setStatus(open.id, 'approved'); setOpen(null); }}>Approve</button>
            </div>
          </div>
        </Modal>
      )}
    </section>
  );
}

// Renders every field the backend returned in `fullApp`, grouped into sections
// for readability: Identity, Socials, Experience, Acknowledgments, then long
// free-form answers, then any uploaded screenshots.
function ApplicationDetail({ row }) {
  const full = row.fullApp || {};
  const LABELS = {
    realName: 'Real name', displayName: 'Display name', region: 'Region',
    languages: 'Languages', email: 'Email', telegram: 'Telegram',
    discord: 'Discord', twitter: 'Twitter', linkedin: 'LinkedIn',
    youtube: 'YouTube', tiktok: 'TikTok', twitch: 'Twitch / Kick',
    portfolio: 'Portfolio', years: 'Years of experience',
    tradingPlatforms: 'Where they trade', monthlyVolume: 'Monthly volume',
    hasRefRevenue: 'Earns referral revenue?', refRevenue: 'Referral revenue',
    tier: 'Applying tier', referral: 'Referral code', ambCode: 'Ambassador code',
    ack_nfa: 'NFA', ack_disc: 'Rewards discretion', ack_conduct: 'Code of conduct',
    q_why: 'Why ambassador', q_success: 'What would make the program successful',
    q_tier: 'Tier qualification', q_else: 'Anything else',
    q_problem: 'Problem Bloom solves', q_diff: 'What makes Bloom different',
    q_links: 'Content links', q_communities: 'Active communities',
    q_friend: 'Explain Bloom to a friend',
  };
  const SECTIONS = [
    { title: 'Identity', keys: ['realName', 'displayName', 'region', 'languages', 'tier'] },
    { title: 'Socials & contact', keys: ['email', 'telegram', 'twitter', 'discord', 'linkedin', 'youtube', 'tiktok', 'twitch', 'portfolio'] },
    { title: 'Experience', keys: ['years', 'tradingPlatforms', 'monthlyVolume', 'hasRefRevenue', 'refRevenue'] },
    { title: 'Codes', keys: ['referral', 'ambCode'] },
    { title: 'Acknowledgments', keys: ['ack_nfa', 'ack_disc', 'ack_conduct'] },
  ];
  const LONG_KEYS = ['q_why', 'q_success', 'q_tier', 'q_else', 'q_diff', 'q_problem', 'q_links', 'q_communities', 'q_friend'];
  const IMAGE_KEYS = ['volumeProof', 'refProof'];

  const labelFor = (k) => LABELS[k] || k;
  const format = (v) => {
    if (Array.isArray(v)) return v.join(', ');
    if (typeof v === 'object' && v !== null) return JSON.stringify(v);
    return String(v);
  };
  const has = (k) => full[k] != null && full[k] !== '' && !(Array.isArray(full[k]) && full[k].length === 0);

  const renderedSections = SECTIONS.map(section => {
    const present = section.keys.filter(has);
    if (present.length === 0) return null;
    return (
      <div key={section.title} className="app-detail-section">
        <div className="app-detail-section-title">{section.title}</div>
        <dl className="app-detail-grid">
          {present.map(k => (
            <React.Fragment key={k}>
              <dt>{labelFor(k)}</dt>
              <dd>{format(full[k])}</dd>
            </React.Fragment>
          ))}
        </dl>
      </div>
    );
  }).filter(Boolean);

  const longPresent = LONG_KEYS.filter(has);
  const imagePresent = IMAGE_KEYS.filter(has);

  return (
    <div className="app-detail">
      {renderedSections}
      {longPresent.length > 0 && (
        <div className="app-detail-section">
          <div className="app-detail-section-title">Answers</div>
          {longPresent.map(k => (
            <div key={k} className="app-detail-long">
              <div className="app-detail-long-label">{labelFor(k)}</div>
              <p>{format(full[k])}</p>
            </div>
          ))}
        </div>
      )}
      {imagePresent.length > 0 && (
        <div className="app-detail-section">
          <div className="app-detail-section-title">Uploads</div>
          {imagePresent.map(k => (
            <div key={k} className="app-detail-long">
              <div className="app-detail-long-label">{labelFor(k)}</div>
              <div className="img-thumbs">
                {(full[k] || []).map(img => (
                  <div key={img.id || img.name} className="img-thumb">
                    <img src={img.dataUrl} alt={img.name || ''}/>
                    <span className="img-thumb-name">{img.name || ''}</span>
                  </div>
                ))}
              </div>
            </div>
          ))}
        </div>
      )}
      {renderedSections.length === 0 && longPresent.length === 0 && imagePresent.length === 0 && (
        <p className="card-sub">No application data on file.</p>
      )}
    </div>
  );
}

function SprintDetailA({ label, body }) {
  return (
    <div className="sprint-detail">
      <div className="mono-label">{label}</div>
      <p>{body}</p>
    </div>
  );
}

function AdminPosts() {
  const [rows, setRows] = useStateA(window.MOCK_REVIEW_POSTS || []);
  const [dirty, setDirty] = useStateA({}); // { [id]: true } once edited locally
  const [savingId, setSavingId] = useStateA(null);

  React.useEffect(() => {
    window._api.getAdminPosts()
      .then(d => { const list = Array.isArray(d) ? d : []; setRows(list); window.MOCK_REVIEW_POSTS = list; })
      .catch(() => {});
  }, []);

  const setRating = (id, v) => {
    setRows(rows.map(r => r.id === id ? { ...r, rating: v } : r));
    setDirty({ ...dirty, [id]: true });
  };
  const setComment = (id, v) => {
    setRows(rows.map(r => r.id === id ? { ...r, comment: v } : r));
    setDirty({ ...dirty, [id]: true });
  };
  const save = async (id) => {
    const r = rows.find(x => x.id === id);
    if (!r) return;
    setSavingId(id);
    try {
      await window._api.updateAdminPost(id, { rating: r.rating, comment: r.comment || null });
      const next = { ...dirty }; delete next[id]; setDirty(next);
    } catch (e) {
      window.ui.toast('Save failed: ' + e.message, { kind: 'error' });
    }
    setSavingId(null);
  };
  return (
    <section className="card">
      <header className="card-head row">
        <div>
          <h2 className="serif-h3">Posts Review</h2>
        </div>
        <div className="card-head-actions">
          <ExportCsvButton kind="posts"/>
          <span className="mono-count">{rows.length}</span>
        </div>
      </header>
      <div className="table-wrap sticky-head">
        <table className="data-table">
          <thead>
            <tr>
              <th>Ambassador</th>
              <th>Post URL</th>
              <th>Sprint</th>
              <th>Type</th>
              <th>Date</th>
              <th>Rating</th>
              <th>Comment</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {rows.map(r => (
              <tr key={r.id}>
                <td>{r.ambassador}</td>
                <td><a className="link" href={window.safeHref(r.url)} target="_blank" rel="noreferrer">{shortUrlA(r.url)}</a></td>
                <td className="mono">{r.sprint ?? '—'}</td>
                <td>{r.type}</td>
                <td className="mono">{fmtDate(r.date)}</td>
                <td>
                  <input className="cell-input mono num small" type="number" min="0" max="10" value={r.rating ?? ''}
                    onChange={(e) => setRating(r.id, e.target.value === '' ? null : Number(e.target.value))}
                    disabled={savingId === r.id}/>
                </td>
                <td>
                  <input className="cell-input" placeholder="Add comment…" value={r.comment || ''}
                    onChange={(e) => setComment(r.id, e.target.value)}
                    disabled={savingId === r.id}/>
                </td>
                <td className="actions-cell">
                  <button
                    className="btn btn-mini ok"
                    onClick={() => save(r.id)}
                    disabled={!dirty[r.id] || savingId === r.id}>
                    {savingId === r.id ? 'Saving…' : 'Apply'}
                  </button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </section>
  );
}

function AdminAmbassadors() {
  const [rows, setRows] = useStateA(window.MOCK_AMBASSADORS || []);

  React.useEffect(() => {
    window._api.getAdminAmbassadors()
      .then(d => { const list = Array.isArray(d) ? d : []; setRows(list); window.MOCK_AMBASSADORS = list; })
      .catch(() => {});
  }, []);

  const setTier = (id, tier) => {
    const row = rows.find(r => r.id === id);
    window._api.updateAdminAmbassador(id, { tier, expectedUpdatedAt: row?.updated_at })
      .then((updated) => { setRows(rows.map(r => r.id === id ? { ...r, tier, updated_at: updated?.updated_at } : r)); window.ui.toast(`Tier set to ${tier}.`, { kind: 'success' }); })
      .catch(err => window.ui.toast(err.message, { kind: 'error' }));
  };
  const promote = (id) => {
    const r = rows.find(x => x.id === id);
    setTier(id, nextTier(r.tier));
  };
  const demote = (id) => {
    const r = rows.find(x => x.id === id);
    setTier(id, prevTier(r.tier));
  };
  const remove = async (id, name) => {
    const ok = await window.ui.confirm({
      title: `Remove ${name} as an ambassador?`,
      message: "They will lose access and revert to 'waiting'. Their posts stay on file.",
      danger: true,
      confirmLabel: 'Remove',
    });
    if (!ok) return;
    window._api.removeAdminAmbassador(id)
      .then(() => { setRows(rows.filter(r => r.id !== id)); window.ui.toast(`${name} removed.`, { kind: 'success' }); })
      .catch(err => window.ui.toast(err.message, { kind: 'error' }));
  };
  return (
    <section className="card">
      <header className="card-head row">
        <div>
          <h2 className="serif-h3">Ambassadors</h2>
        </div>
        <div className="card-head-actions">
          <ExportCsvButton kind="ambassadors"/>
          <span className="mono-count">{rows.length}</span>
        </div>
      </header>
      <div className="table-wrap sticky-head">
        <table className="data-table">
          <thead>
            <tr>
              <th>Name</th><th>Twitter</th><th>Telegram</th><th>Tier</th><th>Posts</th><th>Joined</th><th></th>
            </tr>
          </thead>
          <tbody>
            {rows.map(r => (
              <tr key={r.id}>
                <td><div className="amb-name"><img src={r.avatar} alt=""/><strong>{r.name}</strong></div></td>
                <td className="mono">@{r.handle}</td>
                <td className="mono">{r.telegram ? '@' + r.telegram : <span className="dash">—</span>}</td>
                <td><span className={`tier-mini ${r.tier}`}>{capitalize(r.tier)}</span></td>
                <td className="mono num">{r.posts}</td>
                <td className="mono">{fmtDate(r.joined)}</td>
                <td className="actions-cell">
                  <button className="btn btn-mini" onClick={() => promote(r.id)} disabled={r.tier === 'apex'}>Promote</button>
                  <button className="btn btn-mini ghost" onClick={() => demote(r.id)} disabled={r.tier === 'scout'}>Demote</button>
                  <button className="icon-btn" title="Remove ambassador" onClick={() => remove(r.id, r.name)}>
                    <Icon name="trash" size={14}/>
                  </button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </section>
  );
}

function nextTier(t) { return t === 'scout' ? 'ranger' : t === 'ranger' ? 'apex' : 'apex'; }
function prevTier(t) { return t === 'apex' ? 'ranger' : t === 'ranger' ? 'scout' : 'scout'; }

function AdminSprints() {
  const [rows, setRows] = useStateA([]);
  const [editing, setEditing] = useStateA(null);
  const [creating, setCreating] = useStateA(false);
  const [filter, setFilter] = useStateA('all');

  // Fetch live sprints (admin endpoint returns id, n, status, etc.).
  React.useEffect(() => {
    window._api.getAdminSprints()
      .then(d => setRows(Array.isArray(d) ? d.filter(s => s.title) : []))
      .catch(() => {});
  }, []);

  const update = (n, patch) => {
    const row = rows.find(r => r.n === n);
    if (!row || !row.id) return;
    window._api.updateAdminSprint(row.id, patch)
      .then(() => { setRows(rows.map(r => r.n === n ? { ...r, ...patch } : r)); window.ui.toast('Sprint updated.', { kind: 'success' }); })
      .catch(err => window.ui.toast(err.message, { kind: 'error' }));
  };
  const remove = async (n) => {
    const row = rows.find(r => r.n === n);
    if (!row || !row.id) return;
    const ok = await window.ui.confirm({
      title: `Delete sprint ${String(n).padStart(2, '0')}?`,
      message: row.title ? `"${row.title}" will be removed from the program. This cannot be undone.` : 'This sprint will be removed from the program. This cannot be undone.',
      danger: true,
      confirmLabel: 'Delete',
    });
    if (!ok) return;
    window._api.deleteAdminSprint(row.id)
      .then(() => { setRows(rows.filter(r => r.n !== n)); window.ui.toast('Sprint deleted.', { kind: 'success' }); })
      .catch(err => window.ui.toast(err.message, { kind: 'error' }));
  };
  const add = (s) => {
    const nextN = (rows.length === 0 ? 0 : Math.max(0, ...rows.map(r => r.n)) + 1);
    window._api.createAdminSprint({ ...s, n: nextN, status: s.status || 'pending' })
      .then((created) => { setRows([...rows, created]); window.ui.toast('Sprint created.', { kind: 'success' }); })
      .catch(err => window.ui.toast(err.message, { kind: 'error' }));
  };

  const counts = {
    all: rows.length,
    active: rows.filter(r => r.status === 'active').length,
    pending: rows.filter(r => r.status === 'pending').length,
    ended: rows.filter(r => r.status === 'ended').length,
  };
  const visible = filter === 'all' ? rows : rows.filter(r => r.status === filter);

  return (
    <section className="card">
      <header className="card-head row">
        <div>
          <h2 className="serif-h3">Sprint Management</h2>
        </div>
        <div className="sa-head-right">
          <span className="mono-count">{rows.length}</span>
          <div className="sa-filters">
            {['all', 'active', 'pending', 'ended'].map(f => (
              <button
                key={f}
                className={`sa-filter ${filter === f ? 'on' : ''}`}
                onClick={() => setFilter(f)}>
                {capitalize(f)} <span className="sa-count">{counts[f]}</span>
              </button>
            ))}
          </div>
          <button className="btn btn-primary" onClick={() => setCreating(true)}>
            <Icon name="plus" size={14}/> New sprint
          </button>
        </div>
      </header>

      <div className="sa-grid">
        {visible.map(s => (
          <article key={s.n} className={`sa-card ${s.status}`} onClick={() => setEditing(s)}>
            <header className="sa-card-head">
              <span className="sa-num-chip">{String(s.n).padStart(2, '0')}</span>
              <span className={`sa-status ${s.status}`}>
                <i className="sa-dot"></i>{capitalize(s.status)}
              </span>
            </header>
            <h4 className="sa-title">{s.title}</h4>
            <p className="sa-snippet">{s.snippet}</p>
            <footer className="sa-card-foot mono small">
              <button className="sa-iconlink" onClick={(e) => { e.stopPropagation(); update(s.n, { status: s.status === 'active' ? 'pending' : 'active' }); }}>
                {s.status === 'active' ? 'Pause' : 'Activate'}
              </button>
              {s.status !== 'ended' && (
                <button className="sa-iconlink" onClick={(e) => { e.stopPropagation(); update(s.n, { status: 'ended' }); }} style={{color:'var(--ink-400)'}}>
                  End
                </button>
              )}
              <button className="sa-iconlink danger" onClick={(e) => { e.stopPropagation(); remove(s.n); }}>
                Delete
              </button>
            </footer>
          </article>
        ))}
        {visible.length === 0 && (
          <div className="sa-empty">No sprints match the current filter.</div>
        )}
      </div>

      {editing && (
        <SprintEditModal
          sprint={editing}
          onSave={(patch) => { update(editing.n, patch); setEditing(null); }}
          onDelete={() => { remove(editing.n); setEditing(null); }}
          onClose={() => setEditing(null)}
        />
      )}
      {creating && (
        <SprintEditModal
          sprint={{ title: '', snippet: '', moment: '', objective: '', whatsNew: '', resources: '', status: 'pending' }}
          isNew
          onSave={(patch) => { add(patch); setCreating(false); }}
          onClose={() => setCreating(false)}
        />
      )}
    </section>
  );
}

function SprintEditModal({ sprint, isNew, onSave, onDelete, onClose }) {
  const [s, setS] = useStateA(sprint);
  const set = (k, v) => setS({ ...s, [k]: v });
  const canSave = s.title && s.title.trim().length > 0;
  return (
    <Modal open onClose={onClose}>
      <header className="modal-head">
        <div>
          <span className="mono-label">{isNew ? 'New sprint' : `Sprint ${String(sprint.n).padStart(2, '0')}`}</span>
          <h3 className="serif-h2">{isNew ? 'Create a sprint' : 'Edit sprint'}</h3>
        </div>
        <button className="icon-btn" onClick={onClose}><Icon name="x" size={16}/></button>
      </header>
      <div className="modal-body">
        <div className="field">
          <label className="mono-label">Title</label>
          <input className="input" value={s.title} onChange={(e) => set('title', e.target.value)} placeholder="e.g. Fresh Call"/>
        </div>
        <div className="field">
          <label className="mono-label">Snippet</label>
          <input className="input" value={s.snippet || ''} onChange={(e) => set('snippet', e.target.value)} placeholder="One-line description shown on the card"/>
        </div>
        <div className="field">
          <label className="mono-label">Objective</label>
          <textarea className="textarea" rows="2" value={s.objective || ''} onChange={(e) => set('objective', e.target.value)} placeholder="What an ambassador must do to complete this sprint"/>
        </div>
        <div className="grid-2">
          <div className="field">
            <label className="mono-label">Moment</label>
            <input className="input" value={s.moment || ''} onChange={(e) => set('moment', e.target.value)} placeholder="When this sprint runs"/>
          </div>
          <div className="field">
            <label className="mono-label">What's new</label>
            <input className="input" value={s.whatsNew || ''} onChange={(e) => set('whatsNew', e.target.value)} placeholder="Product changes tied to this sprint"/>
          </div>
        </div>
        <div className="field">
          <label className="mono-label">Resources</label>
          <input className="input" value={s.resources || ''} onChange={(e) => set('resources', e.target.value)} placeholder="Telegram channel, doc link…"/>
        </div>
        <div className="field">
          <label className="mono-label">Status</label>
          <div className="seg">
            {['active', 'pending', 'ended'].map(opt => (
              <button key={opt} className={`seg-btn ${s.status === opt ? 'on' : ''}`} onClick={() => set('status', opt)}>
                {capitalize(opt)}
              </button>
            ))}
          </div>
        </div>
        <div className="modal-actions">
          {!isNew && onDelete && (
            <button className="btn btn-mini bad" onClick={onDelete}>
              <Icon name="trash" size={14}/> Delete
            </button>
          )}
          <div style={{ flex: 1 }}/>
          <button className="btn btn-ghost" onClick={onClose}>Cancel</button>
          <button className="btn btn-primary" disabled={!canSave} onClick={() => onSave(s)}>
            {isNew ? 'Create sprint' : 'Save changes'}
          </button>
        </div>
      </div>
    </Modal>
  );
}

function shortUrlA(u) {
  try {
    const url = new URL(u);
    const tail = (url.pathname.split('/').filter(Boolean).pop() || '');
    return `${url.host.replace(/^www\./,'')}/…${tail.slice(-8)}`;
  } catch { return u; }
}
function capitalize(s) { return s ? s[0].toUpperCase() + s.slice(1) : ''; }

// Small button that triggers a CSV download for the given admin resource.
// Calls window._api.exportCsv which POSTs to /api/admin/export/<kind> and
// turns the response into a Blob + <a download> trigger.
function ExportCsvButton({ kind }) {
  const [busy, setBusy] = useStateA(false);
  const onClick = async () => {
    if (busy) return;
    setBusy(true);
    try {
      const stamp = new Date().toISOString().slice(0, 10);
      await window._api.exportCsv(kind, `${kind}-${stamp}.csv`);
      window.ui && window.ui.toast('CSV downloaded.', { kind: 'success' });
    } catch (e) {
      window.ui && window.ui.toast(e.message || 'Export failed.', { kind: 'error' });
    } finally {
      setBusy(false);
    }
  };
  return (
    <button className="btn btn-mini ghost" onClick={onClick} disabled={busy} title="Download as CSV">
      <Icon name={busy ? 'loader' : 'download'} size={14}/> {busy ? 'Preparing…' : 'Download CSV'}
    </button>
  );
}

window.AdminPage = AdminPage;
