// Admin / Platform Console
// Full-screen settings page. Left subnav · right detail.
// Sections: General · Members · Teams · Engines · Billing · Audit · API keys

const ADMIN_SECTIONS = [
  { id: 'general',   label: 'General',        icon: 'settings', group: 'Workspace' },
  { id: 'members',   label: 'Members',        icon: 'users',    group: 'Workspace' },
  { id: 'teams',     label: 'Teams',          icon: 'team',     group: 'Workspace' },
  { id: 'engines',   label: 'Engines',        icon: 'engine',   group: 'Platform' },
  { id: 'nodes',     label: 'Nodes',          icon: 'server',   group: 'Platform' },
  { id: 'billing',   label: 'Billing & usage', icon: 'database', group: 'Platform' },
  { id: 'audit',     label: 'Audit log',      icon: 'shield',   group: 'Platform' },
  { id: 'apikeys',   label: 'API keys',       icon: 'lock',     group: 'Platform' },
];

const AdminPage = ({ section: initialSection, setSection: setExternalSection }) => {
  const [section, setSection] = React.useState(initialSection || 'general');
  React.useEffect(() => { if (initialSection) setSection(initialSection); }, [initialSection]);
  const onSelect = (id) => { setSection(id); setExternalSection && setExternalSection(id); };

  const groups = {};
  ADMIN_SECTIONS.forEach(s => { (groups[s.group] = groups[s.group] || []).push(s); });

  const cur = ADMIN_SECTIONS.find(s => s.id === section) || ADMIN_SECTIONS[0];

  let body;
  switch (section) {
    case 'general':  body = <AdminGeneral />; break;
    case 'members':  body = <AdminMembers />; break;
    case 'teams':    body = <AdminTeams />; break;
    case 'engines':  body = <AdminEngines />; break;
    case 'nodes':    body = <AdminNodes />; break;
    case 'billing':  body = <AdminBilling />; break;
    case 'audit':    body = <AdminAudit />; break;
    case 'apikeys':  body = <AdminApiKeys />; break;
    default:         body = <AdminGeneral />;
  }

  return (
    <div className="admin-layout fade-in">
      <aside className="admin-nav">
        <div className="admin-nav-head">
          <div className="admin-nav-title">Settings</div>
          <div className="admin-nav-sub">acme · workspace</div>
        </div>
        {Object.entries(groups).map(([g, items]) => (
          <div key={g} className="admin-nav-group">
            <div className="admin-nav-grouplabel">{g}</div>
            {items.map(s => (
              <button
                key={s.id}
                type="button"
                className={`admin-nav-item ${section === s.id ? 'on' : ''}`}
                onClick={() => onSelect(s.id)}
              >
                <Icon name={s.icon} size={14} />
                <span>{s.label}</span>
              </button>
            ))}
          </div>
        ))}
      </aside>

      <div className="admin-main">
        <div className="admin-head">
          <div>
            <div className="admin-title">{cur.label}</div>
            <div className="admin-sub">{ADMIN_SUBTITLES[section] || ''}</div>
          </div>
        </div>
        <div className="admin-body">
          {body}
        </div>
      </div>
    </div>
  );
};

const ADMIN_SUBTITLES = {
  general:  'Workspace name, branding, defaults applied to every project.',
  members:  'Everyone with access to this workspace, across teams and projects.',
  teams:    'Functional groups. Each project belongs to one team for routing and on-call.',
  engines:  'Provider credentials, rate limits, and concurrency caps for every agent engine.',
  nodes:    'Global CLAUDE.md, agent rules, and per-node overrides applied to every run.',
  billing:  'Spend, quotas, and seat utilization across the workspace.',
  audit:    'Every privileged action — invitations, role changes, key rotations.',
  apikeys:  'Programmatic credentials for API access and CI integrations.',
};

// =================== General ===================
const AdminGeneral = () => (
  <div className="admin-stack">
    <AdminCard title="Workspace identity" desc="Shown across the app and on invitations.">
      <div className="admin-form">
        <AdminField label="Name">
          <input className="admin-input" defaultValue="Acme Platform" />
        </AdminField>
        <AdminField label="URL slug" hint="acme.bks.dev">
          <input className="admin-input mono" defaultValue="acme" />
        </AdminField>
        <AdminField label="Logo">
          <div className="admin-logo-row">
            <div className="org-avatar" style={{width: 40, height: 40, fontSize: 14, borderRadius: 8}}>AC</div>
            <button className="ibtn bordered">Upload…</button>
            <button className="ibtn">Remove</button>
          </div>
        </AdminField>
      </div>
    </AdminCard>

    <AdminCard title="Defaults" desc="Apply when a new project is created. Per-project overrides allowed.">
      <div className="admin-form">
        <AdminField label="Time zone">
          <select className="admin-input"><option>Asia/Shanghai · UTC+8</option><option>Europe/Berlin · UTC+1</option><option>America/Los_Angeles · UTC-8</option></select>
        </AdminField>
        <AdminField label="Default engine" hint="Used when a capability matches multiple engines.">
          <select className="admin-input"><option>claude-sonnet-4.5</option><option>codex-gpt-5</option><option>gemini-2.5-pro</option></select>
        </AdminField>
        <AdminField label="Issue ID prefix">
          <input className="admin-input mono" defaultValue="BKS" style={{width: 120}} />
        </AdminField>
      </div>
    </AdminCard>

    <AdminCard title="Danger zone" tone="danger">
      <div className="admin-danger-row">
        <div>
          <div style={{fontWeight: 500, marginBottom: 2}}>Transfer workspace</div>
          <div className="dim" style={{fontSize: 12}}>Move this workspace to another owner. Requires their confirmation.</div>
        </div>
        <button className="ibtn bordered">Transfer…</button>
      </div>
      <div className="admin-danger-row">
        <div>
          <div style={{fontWeight: 500, marginBottom: 2, color: 'var(--status-blocked)'}}>Delete workspace</div>
          <div className="dim" style={{fontSize: 12}}>Permanently delete all projects, issues, and history.</div>
        </div>
        <button className="ibtn" style={{color: 'var(--status-blocked)', border: '1px solid color-mix(in oklch, var(--status-blocked) 30%, transparent)'}}>Delete…</button>
      </div>
    </AdminCard>
  </div>
);

// =================== Members ===================
const ADMIN_MEMBER_ROLES = ['Owner', 'Admin', 'Member', 'Viewer'];

const AdminMembers = () => {
  const [filter, setFilter] = React.useState('all');
  const [q, setQ] = React.useState('');
  const all = AGENTS_BY_ENGINE.human.map((p, i) => ({
    ...p,
    role: i === 0 ? 'Owner' : i < 3 ? 'Admin' : 'Member',
    seat: i % 4 === 0 ? 'Editor' : i % 5 === 0 ? 'Viewer' : 'Editor',
    invited: i > 4 && i % 7 === 0,
    twoFA: i !== 1 && i !== 4,
  }));
  const list = all
    .filter(m => filter === 'all' ? true : (filter === 'pending' ? m.invited : m.role.toLowerCase() === filter))
    .filter(m => q ? (m.name.toLowerCase().includes(q.toLowerCase()) || m.handle.toLowerCase().includes(q.toLowerCase())) : true);

  const counts = {
    all: all.length,
    owner: all.filter(m => m.role === 'Owner').length,
    admin: all.filter(m => m.role === 'Admin').length,
    member: all.filter(m => m.role === 'Member').length,
    pending: all.filter(m => m.invited).length,
  };

  return (
    <div className="admin-stack">
      <div className="admin-toolbar">
        <div className="admin-search">
          <Icon name="search" size={13} />
          <input placeholder="Search members or @handle…" value={q} onChange={e => setQ(e.target.value)} />
        </div>
        <div className="admin-pill-row">
          {[['all','All'],['owner','Owners'],['admin','Admins'],['member','Members'],['pending','Pending']].map(([k, l]) => (
            <button key={k} className={`admin-pill ${filter === k ? 'on' : ''}`} onClick={() => setFilter(k)}>
              {l} <span className="mono dim" style={{fontSize: 10.5}}>{counts[k]}</span>
            </button>
          ))}
        </div>
        <div className="spacer" />
        <button className="ibtn bordered"><Icon name="upload" size={13} /> Export CSV</button>
        <button className="ibtn primary"><Icon name="plus" size={13} /> Invite member</button>
      </div>

      <div className="admin-table-wrap">
        <table className="admin-table">
          <thead>
            <tr>
              <th style={{minWidth: 220}}>Member</th>
              <th>Role</th>
              <th>Teams</th>
              <th>2FA</th>
              <th>Last active</th>
              <th style={{width: 32}}></th>
            </tr>
          </thead>
          <tbody>
            {list.map((m, i) => (
              <tr key={m.handle}>
                <td>
                  <div className="admin-member">
                    <div className="admin-avatar" style={{background: AVATAR_BG[i % AVATAR_BG.length]}}>
                      {m.name.split(' ').map(x => x[0]).join('').slice(0, 2)}
                    </div>
                    <div style={{minWidth: 0}}>
                      <div className="admin-member-name">
                        {m.name}
                        {m.invited && <span className="admin-tag pending">invited</span>}
                      </div>
                      <div className="admin-member-handle mono">{m.handle}</div>
                    </div>
                  </div>
                </td>
                <td>
                  <select className="admin-role-select" defaultValue={m.role}>
                    {ADMIN_MEMBER_ROLES.map(r => <option key={r} value={r}>{r}</option>)}
                  </select>
                </td>
                <td>
                  <div className="admin-team-chips">
                    {(m.projects || []).slice(0, 2).map(pid => {
                      const p = PROJECTS.find(x => x.id === pid);
                      return p && <span key={pid} className="admin-team-chip" style={{borderColor: p.color, color: p.color}}>{p.name.split(' ')[0]}</span>;
                    })}
                    {(m.projects || []).length > 2 && <span className="admin-team-chip dim">+{m.projects.length - 2}</span>}
                  </div>
                </td>
                <td>
                  {m.twoFA
                    ? <span className="admin-2fa on"><Icon name="check" size={11} /> on</span>
                    : <span className="admin-2fa off">off</span>}
                </td>
                <td className="mono dim" style={{fontSize: 11.5}}>{m.invited ? '—' : ['12m','1h','3h','yesterday','2d','5d','3w'][i % 7]}</td>
                <td><button className="ibtn" style={{padding: 0, width: 24}}><Icon name="dots" size={14} /></button></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <AdminCard title="Seats" desc="Editor seats include create/edit/run permissions. Viewers are read-only.">
        <div className="admin-seats">
          <div className="admin-seat-bar">
            <div className="admin-seat-fill" style={{width: '68%'}} />
          </div>
          <div className="admin-seat-meta">
            <span><b>17</b> editors used <span className="dim">/ 25 included</span></span>
            <span className="dim">·</span>
            <span><b>4</b> viewers <span className="dim">/ unlimited</span></span>
            <span className="spacer" />
            <button className="ibtn bordered">Manage plan</button>
          </div>
        </div>
      </AdminCard>
    </div>
  );
};

const AVATAR_BG = [
  'linear-gradient(135deg, #FF9A56, #D97757)',
  'linear-gradient(135deg, #4285F4, #1A56D9)',
  'linear-gradient(135deg, #10A37F, #067A5E)',
  'linear-gradient(135deg, #8B5CF6, #6D3DD9)',
  'linear-gradient(135deg, #E8A317, #B97D08)',
  'linear-gradient(135deg, #E5484D, #B92F33)',
];

// =================== Teams ===================
// Migrated from sidebar. Same shape as the old Teams page but framed inside admin.
const ADMIN_TEAMS = [
  { id: 'platform', name: 'Platform Engineering', desc: 'Core infrastructure and gateway services', members: 9,  projects: ['ATLAS','CORE'], lead: 'Xie Ming',     color: '#3D63FF' },
  { id: 'billing',  name: 'Billing & Growth',     desc: 'Revenue systems and pricing',              members: 6,  projects: ['HELIX'],         lead: 'Mira Vasquez', color: '#8B5CF6' },
  { id: 'frontend', name: 'Frontend',              desc: 'Dashboard and analytics UI',               members: 5,  projects: ['NOVA'],          lead: 'Liu Chao',     color: '#E8A317' },
  { id: 'devops',   name: 'DevOps · SRE',          desc: 'Edge runtime and observability',           members: 7,  projects: ['EDGE','PULSE'],  lead: 'Sara Kim',     color: '#00A870' },
];

const AdminTeams = () => (
  <div className="admin-stack">
    <div className="admin-toolbar">
      <div className="admin-search">
        <Icon name="search" size={13} />
        <input placeholder="Search teams…" />
      </div>
      <div className="spacer" />
      <button className="ibtn bordered"><Icon name="filter" size={13} /> Filter</button>
      <button className="ibtn primary"><Icon name="plus" size={13} /> New team</button>
    </div>

    <div className="admin-team-grid">
      {ADMIN_TEAMS.map(t => (
        <div key={t.id} className="admin-team-card">
          <div className="admin-team-card-head">
            <div className="admin-team-mark" style={{background: t.color}}>{t.name.charAt(0)}</div>
            <div style={{flex: 1, minWidth: 0}}>
              <div className="admin-team-card-name">{t.name}</div>
              <div className="admin-team-card-desc">{t.desc}</div>
            </div>
            <button className="ibtn" style={{padding: 0, width: 26}}><Icon name="dots" size={14} /></button>
          </div>
          <div className="admin-team-card-body">
            <div className="admin-team-stat">
              <div className="admin-team-stat-label">Members</div>
              <div className="admin-team-stat-val mono">{t.members}</div>
            </div>
            <div className="admin-team-stat">
              <div className="admin-team-stat-label">Projects</div>
              <div className="admin-team-stat-val">
                {t.projects.map(pid => {
                  const p = PROJECTS.find(x => x.id === pid);
                  return p && <span key={pid} className="admin-team-projchip" style={{background: p.color}} title={p.name}>{p.id.slice(0, 2)}</span>;
                })}
              </div>
            </div>
            <div className="admin-team-stat">
              <div className="admin-team-stat-label">Lead</div>
              <div className="admin-team-stat-val">{t.lead}</div>
            </div>
          </div>
          <div className="admin-team-card-foot">
            <button className="ibtn">Manage members</button>
            <button className="ibtn">Settings</button>
          </div>
        </div>
      ))}
    </div>
  </div>
);

// =================== Engines ===================
const AdminEngines = () => (
  <div className="admin-stack">
    {ENGINES.map(eng => (
      <AdminCard key={eng.id} title={eng.name} desc={`${eng.vendor} · ${eng.runs.toLocaleString()} runs · ${eng.success}% success`}>
        <div className="admin-form">
          <AdminField label="Status">
            <div className="row" style={{gap: 8}}>
              <span className={`ne-status ${eng.status === 'ready' ? 'ready' : 'degraded'}`}>{eng.status}</span>
              <span className="dim mono" style={{fontSize: 11.5}}>p50 {eng.latency}ms</span>
            </div>
          </AdminField>
          <AdminField label="API key" hint="Last rotated 14 days ago.">
            <div className="row" style={{gap: 8}}>
              <input className="admin-input mono" type="password" defaultValue="sk-••••••••••••••••" readOnly style={{flex: 1}} />
              <button className="ibtn bordered"><Icon name="refresh" size={12} /> Rotate</button>
            </div>
          </AdminField>
          <AdminField label="Concurrency cap" hint="Max parallel runs across the workspace.">
            <input className="admin-input mono" type="number" defaultValue="32" style={{width: 100}} />
          </AdminField>
          <AdminField label="Default model">
            <select className="admin-input">
              {eng.models.map(m => <option key={m.name}>{m.name}</option>)}
            </select>
          </AdminField>
        </div>
      </AdminCard>
    ))}
  </div>
);

// =================== Billing ===================
const AdminBilling = () => (
  <div className="admin-stack">
    <AdminCard title="Plan" desc="Renews monthly · next charge Aug 1.">
      <div className="admin-plan-row">
        <div>
          <div className="admin-plan-name">Team</div>
          <div className="admin-plan-price">$240<span className="dim mono" style={{fontSize: 13}}> / mo</span></div>
          <div className="dim" style={{fontSize: 12, marginTop: 4}}>25 editor seats · unlimited viewers · 100k agent runs / mo</div>
        </div>
        <div style={{display: 'flex', gap: 8}}>
          <button className="ibtn bordered">Cancel plan</button>
          <button className="ibtn primary">Upgrade to Enterprise</button>
        </div>
      </div>
    </AdminCard>

    <div className="admin-kpi-row">
      {[
        { label: 'Spend (MTD)', val: '$184.40', sub: '76% of monthly cap' },
        { label: 'Agent runs',  val: '63,210',  sub: '100,000 included' },
        { label: 'Tokens (in)', val: '94.2M',   sub: '+12% vs last 30d' },
        { label: 'Tokens (out)',val: '38.1M',   sub: '+5% vs last 30d' },
      ].map(k => (
        <div key={k.label} className="admin-kpi">
          <div className="admin-kpi-label">{k.label}</div>
          <div className="admin-kpi-val mono">{k.val}</div>
          <div className="admin-kpi-sub dim">{k.sub}</div>
        </div>
      ))}
    </div>

    <AdminCard title="Engine spend · last 30 days">
      <div className="admin-spend">
        {[
          { name: 'Claude Code',  cost: 92.40, pct: 50 },
          { name: 'Codex',        cost: 58.80, pct: 32 },
          { name: 'Gemini Pro',   cost: 33.20, pct: 18 },
        ].map(e => (
          <div key={e.name} className="admin-spend-row">
            <div className="admin-spend-name">{e.name}</div>
            <div className="admin-spend-bar"><div className="admin-spend-fill" style={{width: e.pct + '%'}} /></div>
            <div className="admin-spend-cost mono">${e.cost.toFixed(2)}</div>
          </div>
        ))}
      </div>
    </AdminCard>

    <AdminCard title="Recent invoices">
      <table className="admin-table">
        <thead><tr><th>Invoice</th><th>Period</th><th>Amount</th><th>Status</th><th></th></tr></thead>
        <tbody>
          {[
            { id: 'INV-2026-07', period: 'Jul 2026', amt: '$240.00', status: 'paid' },
            { id: 'INV-2026-06', period: 'Jun 2026', amt: '$240.00', status: 'paid' },
            { id: 'INV-2026-05', period: 'May 2026', amt: '$220.00', status: 'paid' },
            { id: 'INV-2026-04', period: 'Apr 2026', amt: '$220.00', status: 'paid' },
          ].map(r => (
            <tr key={r.id}>
              <td className="mono">{r.id}</td>
              <td>{r.period}</td>
              <td className="mono">{r.amt}</td>
              <td><span className="chip chip-done">{r.status}</span></td>
              <td><button className="ibtn"><Icon name="external" size={12} /> PDF</button></td>
            </tr>
          ))}
        </tbody>
      </table>
    </AdminCard>
  </div>
);

// =================== Audit ===================
const AdminAudit = () => {
  const events = [
    { t: '14:22', actor: 'Xie Ming',     action: 'invited',  target: 'lin@example.com', kind: 'member' },
    { t: '13:08', actor: 'Rita Chen',    action: 'rotated',  target: 'API key · claude-prod', kind: 'security' },
    { t: '11:45', actor: 'system',       action: 'enforced', target: 'Concurrency cap on Codex (24 → 32)', kind: 'policy' },
    { t: '10:31', actor: 'Mira Vasquez', action: 'changed role of', target: 'Liu Chao → Admin', kind: 'member' },
    { t: '09:15', actor: 'Xie Ming',     action: 'created',  target: 'API key · ci-deploy', kind: 'security' },
    { t: 'yesterday', actor: 'system', action: 'failed login (3x)', target: '@external', kind: 'security' },
    { t: '2d',  actor: 'Sara Kim',      action: 'archived', target: 'Project EDGE-legacy', kind: 'workspace' },
    { t: '3d',  actor: 'Xie Ming',      action: 'updated',  target: 'Workspace name', kind: 'workspace' },
  ];
  const tone = (k) => ({ member: 'var(--accent)', security: 'var(--status-blocked)', policy: 'var(--status-working)', workspace: 'var(--fg-2)' }[k]);
  return (
    <div className="admin-stack">
      <div className="admin-toolbar">
        <div className="admin-search">
          <Icon name="search" size={13} />
          <input placeholder="Search audit log…" />
        </div>
        <div className="admin-pill-row">
          {['All', 'Members', 'Security', 'Policy', 'Workspace'].map(k => (
            <button key={k} className={`admin-pill ${k === 'All' ? 'on' : ''}`}>{k}</button>
          ))}
        </div>
        <div className="spacer" />
        <button className="ibtn bordered"><Icon name="upload" size={13} /> Export</button>
      </div>

      <div className="admin-card">
        <div className="admin-audit">
          {events.map((e, i) => (
            <div key={i} className="admin-audit-row">
              <div className="admin-audit-dot" style={{background: tone(e.kind)}} />
              <div className="mono dim admin-audit-time">{e.t}</div>
              <div className="admin-audit-body">
                <b>{e.actor}</b> <span className="dim">{e.action}</span> {e.target}
              </div>
              <div className="admin-audit-kind mono dim" style={{color: tone(e.kind)}}>{e.kind}</div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};

// =================== API keys ===================
const AdminApiKeys = () => {
  const keys = [
    { name: 'ci-deploy',     prefix: 'bks_live_a8f2…',  scopes: ['read', 'write'], last: '2m ago',  by: 'Xie Ming' },
    { name: 'analytics-ro',  prefix: 'bks_live_5c91…',  scopes: ['read'],          last: '1h ago',  by: 'Rita Chen' },
    { name: 'webhook-prod',  prefix: 'bks_live_e44d…',  scopes: ['webhook'],       last: 'yesterday', by: 'Mira Vasquez' },
    { name: 'old-staging',   prefix: 'bks_live_1118…',  scopes: ['read', 'write'], last: '3 weeks',  by: 'Liu Chao', expired: true },
  ];
  return (
    <div className="admin-stack">
      <div className="admin-toolbar">
        <div className="admin-search">
          <Icon name="search" size={13} />
          <input placeholder="Search keys…" />
        </div>
        <div className="spacer" />
        <button className="ibtn primary"><Icon name="plus" size={13} /> New API key</button>
      </div>

      <div className="admin-card">
        <table className="admin-table">
          <thead>
            <tr><th>Name</th><th>Token</th><th>Scopes</th><th>Last used</th><th>Created by</th><th></th></tr>
          </thead>
          <tbody>
            {keys.map(k => (
              <tr key={k.name} className={k.expired ? 'admin-row-dim' : ''}>
                <td>
                  <div style={{display: 'flex', alignItems: 'center', gap: 6}}>
                    <Icon name="lock" size={12} className="dim" />
                    <span style={{fontWeight: 500}}>{k.name}</span>
                    {k.expired && <span className="admin-tag expired">expired</span>}
                  </div>
                </td>
                <td className="mono" style={{fontSize: 11.5}}>{k.prefix}</td>
                <td>{k.scopes.map(s => <span key={s} className="admin-scope-chip">{s}</span>)}</td>
                <td className="mono dim" style={{fontSize: 11.5}}>{k.last}</td>
                <td className="dim" style={{fontSize: 12}}>{k.by}</td>
                <td><button className="ibtn"><Icon name="dots" size={14} /></button></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <div className="admin-callout">
        <Icon name="alert" size={14} />
        <div>
          <b>Treat keys like passwords.</b> Once created, the full token is shown only once. Rotate on a 90-day cadence and revoke any key that may have leaked.
        </div>
      </div>
    </div>
  );
};

// =================== Atoms ===================
const AdminCard = ({ title, desc, children, tone }) => (
  <section className={`admin-card ${tone === 'danger' ? 'is-danger' : ''}`}>
    {(title || desc) && (
      <header className="admin-card-head">
        {title && <div className="admin-card-title">{title}</div>}
        {desc && <div className="admin-card-desc">{desc}</div>}
      </header>
    )}
    <div className="admin-card-body">{children}</div>
  </section>
);

const AdminField = ({ label, hint, children }) => (
  <div className="admin-field">
    <div className="admin-field-label">{label}</div>
    <div className="admin-field-control">{children}</div>
    {hint && <div className="admin-field-hint">{hint}</div>}
  </div>
);

// =================== Nodes ===================
// Global runtime configuration that every project on every node inherits.
// Three layers, top → bottom precedence: per-project > per-node > global.
// This page edits the global layer + shows per-node override status.

const DEFAULT_CLAUDE_MD = `# CLAUDE.md — workspace-wide

You are an agent operating inside the Acme Platform. Apply these rules to every
run unless a more specific CLAUDE.md (per-node or per-project) overrides them.

## Code style
- Match the surrounding file. Do not reformat unrelated lines.
- Prefer the project's existing utilities over adding new dependencies.
- Keep diffs surgical. Touch the minimum number of files.

## Communication
- Open every PR with a one-line summary, then a "Why" + "Test plan" section.
- Tag @platform-eng on changes that touch the gateway or auth.
- When blocked, post in the issue thread with the exact error and what you tried.

## Safety
- Never commit secrets or .env files. Refuse if asked.
- Never run destructive shell commands without explicit human approval.
- Stop and ask if a task implies deleting more than 100 lines of production code.
`;

const GLOBAL_RULES = [
  { id: 'r-fmt',   label: 'Run formatter before commit',   desc: 'Auto-runs the project\u2019s registered formatter on touched files.', on: true,  scope: 'all' },
  { id: 'r-tests', label: 'Block PR if tests fail',         desc: 'Abort the run if `pnpm test` or registered test command exits non-zero.', on: true,  scope: 'all' },
  { id: 'r-secret',label: 'Scan diffs for secrets',         desc: 'Detect API keys, tokens, and credentials with gitleaks before commit.', on: true,  scope: 'all' },
  { id: 'r-net',   label: 'Restrict outbound network',     desc: 'Allow only the project\u2019s declared hosts. Anything else returns 403.',  on: true,  scope: 'cloud' },
  { id: 'r-fs',    label: 'Confine writes to repo + tmp',  desc: 'Block writes outside the project working tree and `/tmp`.',           on: true,  scope: 'all' },
  { id: 'r-shell', label: 'Require approval for `rm -rf`', desc: 'Pause and ask before any recursive delete or `git push --force`.',     on: true,  scope: 'all' },
  { id: 'r-mem',   label: 'Persist agent memory',           desc: 'Allow agents to write to per-project memory store between runs.',     on: false, scope: 'all' },
  { id: 'r-tel',   label: 'Send telemetry to platform',    desc: 'Anonymized run traces, latency, and tool-call shape. No content.',     on: true,  scope: 'all' },
];

// Skill bundles — named groupings of skills that can be turned on as a unit
// and bound to a node. A node ships with one default bundle; projects can
// override per-issue.
const SKILL_BUNDLES = [
  {
    id: 'bundle-default',
    name: 'Default',
    desc: 'The baseline skills every project gets. Safe, broad coverage.',
    skills: ['skl-01','skl-02','skl-03','skl-04'],
    builtIn: true,
    nodes: 4,
  },
  {
    id: 'bundle-backend',
    name: 'Backend services',
    desc: 'Schema migrations, API scaffolds, security audits. For platform + core repos.',
    skills: ['skl-05','skl-06','skl-08','skl-01'],
    builtIn: false,
    nodes: 2,
  },
  {
    id: 'bundle-frontend',
    name: 'Frontend & i18n',
    desc: 'Type-only refactors, i18n extraction, PR descriptions \u2014 web-app shaped.',
    skills: ['skl-09','skl-07','skl-01','skl-02'],
    builtIn: false,
    nodes: 1,
  },
  {
    id: 'bundle-triage',
    name: 'Triage-only',
    desc: 'Read-only skills. Used on shared/external nodes where writes are blocked.',
    skills: ['skl-04','skl-02'],
    builtIn: false,
    nodes: 1,
  },
];

const AdminNodes = () => {
  const [tab, setTab]         = React.useState('global');  // global | rules | bundles | overrides
  const [md, setMd]           = React.useState(DEFAULT_CLAUDE_MD);
  const [rules, setRules]     = React.useState(GLOBAL_RULES);
  const [bundles, setBundles] = React.useState(SKILL_BUNDLES);
  const [openBundle, setOpenBundle] = React.useState(null);

  const toggleRule = (id) => setRules(rs => rs.map(r => r.id === id ? {...r, on: !r.on} : r));

  const tabs = [
    { id: 'global',    label: 'CLAUDE.md',     hint: 'Workspace-wide system prompt' },
    { id: 'rules',     label: 'Rules',         hint: `${rules.filter(r=>r.on).length}/${rules.length} active` },
    { id: 'bundles',   label: 'Skill bundles', hint: `${bundles.length} configured` },
    { id: 'overrides', label: 'Overrides', hint: `${NODES.length} nodes` },
  ];

  return (
    <div className="admin-stack">
      <div className="adn-tabs">
        {tabs.map(t => (
          <button key={t.id} className={`adn-tab ${tab===t.id?'on':''}`} onClick={() => setTab(t.id)}>
            <span>{t.label}</span>
            <span className="adn-tab-hint">{t.hint}</span>
          </button>
        ))}
      </div>

      {tab === 'global' && (
        <AdminCard
          title="Global CLAUDE.md"
          desc="Prepended to every agent run on every node. Per-node and per-project files extend this; they don't replace it."
        >
          <div className="adn-md">
            <div className="adn-md-toolbar">
              <span className="dim mono" style={{fontSize:11}}>workspace/CLAUDE.md</span>
              <span className="spacer" />
              <span className="dim" style={{fontSize:11}}>{md.split('\n').length} lines · {md.length} chars</span>
              <button className="ibtn ghost"><Icon name="refresh" size={11} /> Reset to default</button>
              <button className="ibtn primary"><Icon name="check" size={11} /> Save</button>
            </div>
            <textarea
              className="adn-md-area mono"
              value={md}
              onChange={(e) => setMd(e.target.value)}
              spellCheck={false}
            />
            <div className="adn-md-foot">
              <Icon name="info" size={11} className="dim" />
              <span className="dim" style={{fontSize:11}}>
                Changes propagate to all 4 nodes within 60 seconds. Active runs use the version they started with.
              </span>
            </div>
          </div>
        </AdminCard>
      )}

      {tab === 'rules' && (
        <AdminCard
          title="Global rules"
          desc="Hard constraints applied to every run. Toggle off only if you know which projects rely on the behavior."
        >
          <div className="adn-rules">
            {rules.map(r => (
              <div key={r.id} className={`adn-rule ${r.on?'on':''}`}>
                <button
                  type="button"
                  className={`adn-switch ${r.on?'on':''}`}
                  onClick={() => toggleRule(r.id)}
                  aria-label={r.on ? 'Disable' : 'Enable'}
                >
                  <span className="adn-switch-thumb" />
                </button>
                <div className="adn-rule-text">
                  <div className="adn-rule-label">
                    {r.label}
                    {r.scope !== 'all' && <span className="adn-scope">{r.scope} only</span>}
                  </div>
                  <div className="adn-rule-desc">{r.desc}</div>
                </div>
                <button className="ibtn ghost" title="Edit conditions">
                  <Icon name="settings" size={12} />
                </button>
              </div>
            ))}
          </div>
        </AdminCard>
      )}

      {tab === 'bundles' && (
        <>
          <AdminCard
            title="Skill bundles"
            desc="Group skills into reusable presets. Bind a bundle to a node and every project on it inherits the set."
          >
            <div className="adn-bundle-toolbar">
              <span className="dim" style={{fontSize:12}}>
                {bundles.length} bundles · covering {new Set(bundles.flatMap(b=>b.skills)).size}/{SKILLS.length} skills
              </span>
              <span className="spacer" />
              <button className="ibtn bordered"><Icon name="plus" size={11} /> New bundle</button>
            </div>
            <div className="adn-bundle-grid">
              {bundles.map(b => (
                <div key={b.id} className={`adn-bundle ${openBundle===b.id?'open':''}`}>
                  <div className="adn-bundle-head" onClick={() => setOpenBundle(openBundle===b.id?null:b.id)}>
                    <div className="adn-bundle-title">
                      <Icon name={openBundle===b.id?'chevDown':'chevRight'} size={11} className="dim" />
                      <span>{b.name}</span>
                      {b.builtIn && <span className="adn-tag-builtin">built-in</span>}
                    </div>
                    <div className="adn-bundle-stats">
                      <span><b>{b.skills.length}</b> skills</span>
                      <span className="dim">·</span>
                      <span><b>{b.nodes}</b> {b.nodes===1?'node':'nodes'}</span>
                    </div>
                  </div>
                  <div className="adn-bundle-desc">{b.desc}</div>
                  <div className="adn-bundle-skills">
                    {b.skills.map(sid => {
                      const s = SKILLS.find(x => x.id === sid);
                      if (!s) return null;
                      return (
                        <span key={sid} className="adn-skill-chip">
                          <Icon name={s.icon} size={11} />
                          {s.name}
                        </span>
                      );
                    })}
                    {!b.builtIn && (
                      <button className="adn-skill-chip add">
                        <Icon name="plus" size={10} /> add
                      </button>
                    )}
                  </div>
                  {openBundle===b.id && (
                    <div className="adn-bundle-detail">
                      <div className="adn-bundle-detail-row">
                        <span className="dim" style={{fontSize:11,minWidth:90}}>Bundle ID</span>
                        <span className="mono" style={{fontSize:11.5}}>{b.id}</span>
                      </div>
                      <div className="adn-bundle-detail-row">
                        <span className="dim" style={{fontSize:11,minWidth:90}}>Bound to</span>
                        <div className="adn-bundle-nodes">
                          {NODES.slice(0, b.nodes).map(n => (
                            <span key={n.id} className="adn-node-chip">
                              <Icon name="server" size={10} />
                              {n.name}
                            </span>
                          ))}
                        </div>
                      </div>
                      <div className="adn-bundle-actions">
                        {!b.builtIn && <button className="ibtn ghost"><Icon name="edit" size={11} /> Edit</button>}
                        <button className="ibtn ghost"><Icon name="copy" size={11} /> Duplicate</button>
                        {!b.builtIn && <button className="ibtn ghost danger"><Icon name="trash" size={11} /> Delete</button>}
                      </div>
                    </div>
                  )}
                </div>
              ))}
            </div>
          </AdminCard>
          <AdminCard
            title="All available skills"
            desc={`${SKILLS.length} skills in the workspace library. Drop any of them into a bundle.`}
          >
            <div className="adn-skill-list">
              {SKILLS.map(s => {
                const used = bundles.filter(b => b.skills.includes(s.id)).length;
                return (
                  <div key={s.id} className="adn-skill-row">
                    <Icon name={s.icon} size={13} className="dim" />
                    <div style={{flex:1, minWidth:0}}>
                      <div style={{fontSize:13}}>{s.name}</div>
                      <div className="dim" style={{fontSize:11.5, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap'}}>{s.desc}</div>
                    </div>
                    <span className="dim mono" style={{fontSize:11}}>{s.runs.toLocaleString()} runs</span>
                    {used > 0
                      ? <span className="adn-skill-used">in {used} bundle{used>1?'s':''}</span>
                      : <span className="adn-skill-unused">unused</span>}
                  </div>
                );
              })}
            </div>
          </AdminCard>
        </>
      )}

      {tab === 'overrides' && (
        <AdminCard
          title="Per-node overrides"
          desc="Each node can extend or replace the global config. Click a node to edit its CLAUDE.md, rule overrides, or skill bundle binding."
        >
          <table className="admin-table">
            <thead>
              <tr>
                <th>Node</th>
                <th>CLAUDE.md</th>
                <th>Rule overrides</th>
                <th>Skill bundle</th>
                <th>Last sync</th>
              </tr>
            </thead>
            <tbody>
              {NODES.map((n, i) => {
                const hasMd       = i % 2 === 1;
                const ruleOver    = [0, 2, 1, 0][i] || 0;
                const bundleId    = ['bundle-default','bundle-backend','bundle-default','bundle-triage'][i] || 'bundle-default';
                const bundle      = bundles.find(b => b.id === bundleId);
                const sync        = ['12s','1m','3m','just now'][i];
                return (
                  <tr key={n.id} className="adn-node-row">
                    <td>
                      <div className="row" style={{gap:8, alignItems:'center'}}>
                        <span className={`adn-dot ${n.status}`} />
                        <span className="mono" style={{fontSize:12.5}}>{n.name}</span>
                        <span className="dim" style={{fontSize:11}}>{n.region}</span>
                      </div>
                    </td>
                    <td>
                      {hasMd
                        ? <span className="adn-cell-on"><Icon name="file" size={11}/> custom</span>
                        : <span className="dim" style={{fontSize:11.5}}>inherits global</span>}
                    </td>
                    <td>
                      {ruleOver > 0
                        ? <span className="adn-cell-on">{ruleOver} override{ruleOver>1?'s':''}</span>
                        : <span className="dim" style={{fontSize:11.5}}>none</span>}
                    </td>
                    <td>
                      <span className="adn-bundle-pill">
                        <Icon name="skills" size={10} />
                        {bundle?.name || 'Default'}
                      </span>
                    </td>
                    <td className="dim mono" style={{fontSize:11.5}}>{sync}</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </AdminCard>
      )}
    </div>
  );
};

Object.assign(window, { AdminPage, ADMIN_SECTIONS });
