// Admin.jsx — Skjult admin-side for AI-administrasjon (#/admin).
//
// Kun synlig for admin (user_profiles.is_admin = true). Ruten ligger IKKE i
// toppmenyen — inngangen er navnet i avatar-menyen (med ADMIN-merke). Ekte
// sikkerhet ligger i RLS: ikke-admin kan ikke skrive til AI-tabellene uansett,
// og denne siden viser «Ingen tilgang» for dem.
//
// Designstandard (CLAUDE.md): normale kort (.pro-card), modaler i .is-*-skall,
// «legg til» via <QuickAddNewBtn> + kort-modal. Ingen window.prompt/confirm/alert.

const { useState: useAdmState, useEffect: useAdmEffect } = React;

function admLang() { return localStorage.getItem('el-lang') || 'no'; }

// ── Liten bekreftelse (slette modell) — samme mønster som GoalConfirm ──
function AdminConfirm({ open, title, message, confirmLabel, cancelLabel, onConfirm, onCancel }) {
  useAdmEffect(() => {
    if (!open) return;
    function onKey(e) { if (e.key === 'Escape') onCancel(); }
    document.addEventListener('keydown', onKey);
    document.body.style.overflow = 'hidden';
    return () => { document.removeEventListener('keydown', onKey); document.body.style.overflow = ''; };
  }, [open, onCancel]);
  if (!open) return null;
  return ReactDOM.createPortal(
    <div className="is-wrap" onClick={onCancel}>
      <div className="is-card gd-confirm" onClick={e => e.stopPropagation()} style={{ maxWidth: 400 }}>
        <div className="is-head">
          <span className="is-title">{title}</span>
          <button type="button" className="is-close" onClick={onCancel} aria-label="Lukk"><i className="ti ti-x"></i></button>
        </div>
        <div className="is-body">
          <p className="gd-confirm-msg">{message}</p>
          <div className="is-actions">
            <div style={{ flex: 1 }} />
            <button type="button" className="is-btn-cancel" onClick={onCancel}>{cancelLabel}</button>
            <button type="button" className="is-btn-del" onClick={onConfirm}><i className="ti ti-trash"></i><span>{confirmLabel}</span></button>
          </div>
        </div>
      </div>
    </div>,
    document.body
  );
}

// ── «Legg til modell» — kort-modal med to felt (visningsnavn + modell-ID) ──
function AdminAddModelModal({ open, title, idPlaceholder, namePlaceholder, onClose, onSave }) {
  const [name, setName] = useAdmState('');
  const [modelId, setModelId] = useAdmState('');
  const [busy, setBusy] = useAdmState(false);
  const [err, setErr] = useAdmState('');
  useAdmEffect(() => { if (open) { setName(''); setModelId(''); setErr(''); setBusy(false); } }, [open]);
  if (!open) return null;
  const en = admLang() === 'en';
  async function save() {
    if (!name.trim() || !modelId.trim()) { setErr(en ? 'Fill in both fields' : 'Fyll inn begge felt'); return; }
    setBusy(true); setErr('');
    const r = await onSave(name.trim(), modelId.trim());
    setBusy(false);
    if (r && r.error) { setErr(r.error); return; }
    onClose();
  }
  return ReactDOM.createPortal(
    <div className="is-wrap" onClick={onClose}>
      <div className="is-card" onClick={e => e.stopPropagation()} style={{ maxWidth: 440 }}>
        <div className="is-head">
          <span className="is-title">{title}</span>
          <button type="button" className="is-close" onClick={onClose} aria-label="Lukk"><i className="ti ti-x"></i></button>
        </div>
        <div className="is-body">
          <div className="is-field">
            <label className="is-label">{en ? 'Display name' : 'Visningsnavn'}</label>
            <input className="is-input" value={name} autoFocus maxLength={100}
              placeholder={namePlaceholder} onChange={e => setName(e.target.value)}
              onKeyDown={e => { if (e.key === 'Enter') save(); }} />
          </div>
          <div className="is-field">
            <label className="is-label">{en ? 'Model ID' : 'Modell-ID'}</label>
            <input className="is-input" value={modelId} maxLength={256}
              placeholder={idPlaceholder} onChange={e => setModelId(e.target.value)}
              onKeyDown={e => { if (e.key === 'Enter') save(); }} />
          </div>
          {err && <p style={{ color: '#ff4c4c', fontSize: 12, margin: 0 }}>{err}</p>}
          <div className="is-actions">
            <div style={{ flex: 1 }} />
            <button type="button" className="is-btn-cancel" onClick={onClose}>{en ? 'Cancel' : 'Avbryt'}</button>
            <button type="button" className="is-btn-save" disabled={busy} onClick={save}>
              <i className="ti ti-check"></i><span>{busy ? (en ? 'Saving…' : 'Lagrer…') : (en ? 'Add' : 'Legg til')}</span>
            </button>
          </div>
        </div>
      </div>
    </div>,
    document.body
  );
}

// ── Én rad i en modell-liste ──
function AdminModelRow({ model, active, onSetActive, onDelete }) {
  const en = admLang() === 'en';
  return (
    <div className="adm-row">
      <div className="adm-row-main">
        <span className="adm-row-name">{model.display_name}</span>
        <span className="adm-row-id">{model.model_id}</span>
      </div>
      <button
        type="button"
        className={`adm-pill${active ? ' is-active' : ''}`}
        onClick={() => !active && onSetActive(model)}
        title={active ? (en ? 'Active model' : 'Aktiv modell') : (en ? 'Set as active' : 'Sett som aktiv')}
      >
        <i className={`ti ${active ? 'ti-circle-check-filled' : 'ti-circle'}`}></i>
        <span>{active ? (en ? 'Active' : 'Aktiv') : (en ? 'Set active' : 'Sett aktiv')}</span>
      </button>
      <button type="button" className="adm-del" onClick={() => onDelete(model)} title={en ? 'Delete' : 'Slett'}>
        <i className="ti ti-trash"></i>
      </button>
    </div>
  );
}

// Kompakt tallformat: 1 234 → «1.2k», 1 200 000 → «1.2M».
function admFmt(n) {
  n = Number(n) || 0;
  if (n >= 1000000) return (n / 1000000).toFixed(n >= 10000000 ? 0 : 1).replace(/\.0$/, '') + 'M';
  if (n >= 1000) return (n / 1000).toFixed(n >= 10000 ? 0 : 1).replace(/\.0$/, '') + 'k';
  return String(n);
}

// ── KPI-tiles øverst på admin-siden: brukere, aktive siste uke, AI-kvote ──
function AdmKpiTiles({ stats, T }) {
  const loading = !stats;
  const total = stats ? stats.totalUsers : 0;
  const active = stats ? (stats.activeUsersLastWeek != null ? stats.activeUsersLastWeek : stats.newUsersLastWeek) : 0;
  const tokens = stats ? stats.tokensThisMonth : 0;
  const usersMonth = stats ? stats.usersThisMonth : 0;
  const limit = stats ? stats.monthlyTokenLimit : 0;
  // «Kvote brukt» = samlet forbruk denne mnd mot samlet kvote (limit × aktive AI-brukere).
  const cap = limit * Math.max(usersMonth, 1);
  const pct = cap ? Math.min(999, Math.round((tokens / cap) * 100)) : 0;
  const val = loading ? '–' : undefined;
  return (
    <div className="adm-kpis">
      <div className="adm-kpi">
        <div className="adm-kpi-ico"><i className="ti ti-users"></i></div>
        <div className="adm-kpi-main">
          <span className="adm-kpi-val">{val ?? admFmt(total)}</span>
          <span className="adm-kpi-lbl">{T.kpiUsers}</span>
          <span className="adm-kpi-sub">{T.kpiUsersSub}</span>
        </div>
      </div>
      <div className="adm-kpi">
        <div className="adm-kpi-ico"><i className="ti ti-login-2"></i></div>
        <div className="adm-kpi-main">
          <span className="adm-kpi-val">{val ?? admFmt(active)}</span>
          <span className="adm-kpi-lbl">{T.kpiActive}</span>
          <span className="adm-kpi-sub">{T.kpiActiveSub}</span>
        </div>
      </div>
      <div className="adm-kpi">
        <div className="adm-kpi-ico"><i className="ti ti-gauge"></i></div>
        <div className="adm-kpi-main">
          <span className="adm-kpi-val">{val ?? admFmt(tokens)}</span>
          <span className="adm-kpi-lbl">{T.kpiQuota}</span>
          <span className="adm-kpi-sub">{T.kpiQuotaSub}</span>
          {!loading && cap > 0 && (
            <span className="adm-kpi-bar"><span style={{ width: Math.min(100, pct) + '%' }} /></span>
          )}
        </div>
      </div>
    </div>
  );
}

// ── Liten status-linje ──
function AdmStatus({ msg }) {
  if (!msg) return null;
  const color = msg.kind === 'error' ? '#ff4c4c' : (msg.kind === 'ok' ? 'var(--accent)' : 'var(--sec)');
  return <span style={{ fontSize: 12, fontWeight: 600, color }}>{msg.text}</span>;
}

function Admin() {
  const en = admLang() === 'en';
  const T = {
    title: en ? 'AI administration' : 'AI-administrasjon',
    sub: en ? 'Admin only — models, secrets and quotas for EasyLife AI' : 'Kun admin — modeller, secrets og kvoter for EasyLife AI',
    denied: en ? 'No access' : 'Ingen tilgang',
    deniedBody: en ? 'You must be signed in as an admin to view this page.' : 'Du må være innlogget som admin for å se denne siden.',
    text: en ? 'Text AI' : 'AI · Tekst',
    image: en ? 'Image AI · Runware' : 'AI · Bilde · Runware',
    quotas: en ? 'Quotas' : 'Kvoter',
    provider: en ? 'Provider' : 'Leverandør',
    secret: en ? 'Secret name (Supabase Vault)' : 'Secret-navn (Supabase Vault)',
    save: en ? 'Save' : 'Lagre',
    models: en ? 'Models' : 'Modeller',
    addModel: en ? 'Add model' : 'Legg til modell',
    noModels: en ? 'No models yet.' : 'Ingen modeller ennå.',
    test: en ? 'Test' : 'Test',
    testText: en ? 'Test the selected text model' : 'Test valgt tekstmodell',
    testImage: en ? 'Test the selected image model' : 'Test valgt bildemodell',
    generate: en ? 'Generate' : 'Generer',
    textMonthly: en ? 'Text tokens per user / month' : 'Tekst-tokens pr. bruker / måned',
    imageWeekly: en ? 'Images per user / week' : 'Bilder pr. bruker / uke',
    overview: en ? 'Overview' : 'Oversikt',
    settings: en ? 'Settings' : 'Innstillinger',
    kpiUsers: en ? 'Users' : 'Antall brukere',
    kpiUsersSub: en ? 'total registered' : 'registrert totalt',
    kpiActive: en ? 'Signed in (7 days)' : 'Logget inn (7 dager)',
    kpiActiveSub: en ? 'active last week' : 'aktive siste uke',
    kpiQuota: en ? 'AI quota used' : 'AI-kvote brukt',
    kpiQuotaSub: en ? 'tokens this month' : 'tokens denne måneden',
  };

  const [phase, setPhase] = useAdmState('loading'); // loading | denied | ready
  const [provider, setProvider] = useAdmState('openai');
  const [secrets, setSecrets] = useAdmState({});
  const [secretDraft, setSecretDraft] = useAdmState('');
  const [textModels, setTextModels] = useAdmState([]);
  const [activeTextModel, setActiveTextModel] = useAdmState('');
  const [imgModels, setImgModels] = useAdmState([]);
  const [activeImgModel, setActiveImgModel] = useAdmState('');
  const [imgSecret, setImgSecret] = useAdmState('');
  const [quotas, setQuotas] = useAdmState({ textMonthlyTokens: 500000, imageWeekly: 50 });
  const [stats, setStats] = useAdmState(null); // KPI-tall (brukere + AI-forbruk)

  // status pr. seksjon
  const [stText, setStText] = useAdmState(null);
  const [stImg, setStImg] = useAdmState(null);
  const [stQuota, setStQuota] = useAdmState(null);

  // modaler
  const [addTextOpen, setAddTextOpen] = useAdmState(false);
  const [addImgOpen, setAddImgOpen] = useAdmState(false);
  const [confirmDel, setConfirmDel] = useAdmState(null); // { kind:'text'|'image', model }

  // test-paneler
  const [textTestIn, setTextTestIn] = useAdmState('');
  const [textTestOut, setTextTestOut] = useAdmState('');
  const [textTesting, setTextTesting] = useAdmState(false);
  const [imgTestPrompt, setImgTestPrompt] = useAdmState('');
  const [imgTestUrl, setImgTestUrl] = useAdmState('');
  const [imgTesting, setImgTesting] = useAdmState(false);

  // ── Last konfig ──
  async function loadAll() {
    const { secrets: secs } = await window.elAi.getProviderSecrets();
    setSecrets(secs);
    const active = await window.elAi.getActiveTextConfig();
    setProvider(active.provider || 'openai');
    setSecretDraft(secs[active.provider || 'openai'] || '');
    const { models } = await window.elAi.getTextModels(active.provider || 'openai');
    setTextModels(models);
    setActiveTextModel(active.model || '');
    const img = await window.elAi.getActiveImageConfig();
    setActiveImgModel(img.model || '');
    setImgSecret(img.secretName || '');
    const { models: im } = await window.elAi.getImageModels();
    setImgModels(im);
    const q = await window.elAi.getQuotas();
    setQuotas(q);
    // KPI-tall lastes parallelt (egne RPC-er); feiler stille → tiles viser «–».
    window.elAi.getAdminStats().then(setStats).catch(() => {});
  }

  useAdmEffect(() => {
    let alive = true;
    (async () => {
      const ok = await window.elAi.isCurrentUserAdmin();
      if (!alive) return;
      if (!ok) { setPhase('denied'); return; }
      await loadAll();
      if (!alive) return;
      setPhase('ready');
    })();
    return () => { alive = false; };
  }, []);

  // Bytt provider → persistér som aktiv provider, last secret + modeller + aktiv modell
  async function changeProvider(p) {
    setProvider(p);
    setSecretDraft(secrets[p] || '');
    setStText(null);
    await window.elAi.setActiveTextProvider(p);
    const { models } = await window.elAi.getTextModels(p);
    setTextModels(models);
    const cfg = await window.elAi.getActiveTextConfig();
    setActiveTextModel(cfg.model || '');
  }

  async function saveTextSecret() {
    setStText({ kind: 'info', text: en ? 'Saving…' : 'Lagrer…' });
    const r = await window.elAi.setProviderSecret(provider, secretDraft.trim());
    if (r.success) {
      setSecrets(s => ({ ...s, [provider]: secretDraft.trim() }));
      setStText({ kind: 'ok', text: en ? 'Saved' : 'Lagret' });
    } else setStText({ kind: 'error', text: r.error });
  }

  async function setActiveText(model) {
    const r = await window.elAi.setActiveTextModel(provider, model.model_id);
    if (r.success) { setActiveTextModel(model.model_id); setStText({ kind: 'ok', text: (en ? 'Active: ' : 'Aktiv: ') + model.display_name }); }
    else setStText({ kind: 'error', text: r.error });
  }

  async function addTextModel(name, id) {
    const r = await window.elAi.addTextModel(provider, name, id);
    if (r.success) { const { models } = await window.elAi.getTextModels(provider); setTextModels(models); }
    return r;
  }

  async function setActiveImg(model) {
    const r = await window.elAi.setActiveImageModel(model.model_id);
    if (r.success) { setActiveImgModel(model.model_id); setStImg({ kind: 'ok', text: (en ? 'Active: ' : 'Aktiv: ') + model.display_name }); }
    else setStImg({ kind: 'error', text: r.error });
  }

  async function addImgModel(name, id) {
    const r = await window.elAi.addImageModel(name, id);
    if (r.success) { const { models } = await window.elAi.getImageModels(); setImgModels(models); }
    return r;
  }

  async function saveImgSecret() {
    setStImg({ kind: 'info', text: en ? 'Saving…' : 'Lagrer…' });
    const r = await window.elAi.setImageSecretName(imgSecret.trim());
    setStImg(r.success ? { kind: 'ok', text: en ? 'Saved' : 'Lagret' } : { kind: 'error', text: r.error });
  }

  async function confirmDelete() {
    const item = confirmDel;
    setConfirmDel(null);
    if (!item) return;
    if (item.kind === 'text') {
      const r = await window.elAi.deleteTextModel(item.model.id);
      if (r.success) { const { models } = await window.elAi.getTextModels(provider); setTextModels(models); setStText({ kind: 'ok', text: en ? 'Deleted' : 'Slettet' }); }
      else setStText({ kind: 'error', text: r.error });
    } else {
      const r = await window.elAi.deleteImageModel(item.model.id);
      if (r.success) { const { models } = await window.elAi.getImageModels(); setImgModels(models); setStImg({ kind: 'ok', text: en ? 'Deleted' : 'Slettet' }); }
      else setStImg({ kind: 'error', text: r.error });
    }
  }

  async function saveQuotas() {
    setStQuota({ kind: 'info', text: en ? 'Saving…' : 'Lagrer…' });
    const r = await window.elAi.setQuotas(quotas);
    setStQuota(r.success ? { kind: 'ok', text: en ? 'Saved' : 'Lagret' } : { kind: 'error', text: r.error });
  }

  async function runTextTest() {
    if (!textTestIn.trim()) return;
    setTextTesting(true); setTextTestOut(''); setStText(null);
    try {
      const secretName = secrets[provider] || secretDraft.trim();
      const { content } = await window.elAi.text({
        feature: 'admin_test', prompt: textTestIn.trim(), provider, model: activeTextModel, secretName,
      });
      setTextTestOut(content || (en ? '(empty response)' : '(tomt svar)'));
    } catch (e) { setTextTestOut(''); setStText({ kind: 'error', text: e.message }); }
    setTextTesting(false);
  }

  async function runImgTest() {
    if (!imgTestPrompt.trim()) return;
    setImgTesting(true); setImgTestUrl(''); setStImg(null);
    try {
      const { url } = await window.elAi.image({
        prompt: imgTestPrompt.trim(), model: activeImgModel, secretName: imgSecret.trim(), width: 512, height: 512, track: false,
      });
      setImgTestUrl(url);
    } catch (e) { setStImg({ kind: 'error', text: e.message }); }
    setImgTesting(false);
  }

  if (phase === 'loading') {
    return (
      <div className="v2-page" style={{ alignItems: 'center', justifyContent: 'center', minHeight: '60vh' }}>
        <div style={{ width: 36, height: 36, borderRadius: '50%', border: '3px solid var(--accent)', borderTopColor: 'transparent', animation: 'spin 1s linear infinite' }} />
      </div>
    );
  }

  if (phase === 'denied') {
    return (
      <div className="v2-page adm-page">
        <div className="pro-card" style={{ maxWidth: 480, margin: '40px auto', textAlign: 'center' }}>
          <i className="ti ti-lock" style={{ fontSize: 32, color: 'var(--mut)' }}></i>
          <h2 style={{ margin: '10px 0 6px', fontSize: 18 }}>{T.denied}</h2>
          <p style={{ color: 'var(--sec)', fontSize: 14, margin: 0 }}>{T.deniedBody}</p>
          <a href="#/dashboard" className="is-btn-cancel" style={{ marginTop: 16, textDecoration: 'none' }}>
            <i className="ti ti-arrow-left"></i><span>{en ? 'Back home' : 'Tilbake til Hjem'}</span>
          </a>
        </div>
        <AdmStyle />
      </div>
    );
  }

  return (
    <div className="v2-page adm-page">
      <div className="rt-head">
        <div className="rt-head-l">
          <h1 className="rt-title">{T.title}</h1>
          <span className="rt-date">{T.sub}</span>
        </div>
      </div>

      {/* ── KPI-tiles øverst: nøkkelinfo til admin ── */}
      <div className="adm-section-eyebrow">{T.overview}</div>
      <AdmKpiTiles stats={stats} T={T} />

      {/* Horisontal skillestrek mellom info og innstillinger */}
      <div className="adm-hr" />
      <div className="adm-section-eyebrow">{T.settings}</div>

      <div className="adm-grid">
        {/* ── AI Tekst ── */}
        <section className="pro-card adm-card">
          <div className="adm-card-head">
            <h2 className="adm-card-title"><i className="ti ti-message-2"></i>{T.text}</h2>
            <AdmStatus msg={stText} />
          </div>

          <div className="adm-form-row">
            <div className="is-field" style={{ minWidth: 160 }}>
              <label className="is-label">{T.provider}</label>
              <select className="is-input" value={provider} onChange={e => changeProvider(e.target.value)}>
                <option value="openai">OpenAI</option>
                <option value="gemini">Google Gemini</option>
                <option value="openrouter">OpenRouter</option>
              </select>
            </div>
            <div className="is-field" style={{ flex: 1, minWidth: 180 }}>
              <label className="is-label">{T.secret}</label>
              <div style={{ display: 'flex', gap: 8 }}>
                <input className="is-input" value={secretDraft} placeholder="f.eks. EasylifeAPI_v1"
                  onChange={e => setSecretDraft(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') saveTextSecret(); }} />
                <button type="button" className="is-btn-save" onClick={saveTextSecret}><i className="ti ti-check"></i><span>{T.save}</span></button>
              </div>
            </div>
          </div>

          <div className="adm-sub">
            <div className="adm-sub-head">
              <span className="adm-sub-title">{T.models}</span>
              <QuickAddNewBtn label={T.addModel} onClick={() => setAddTextOpen(true)} />
            </div>
            <div className="adm-list">
              {textModels.length === 0 && <p className="adm-empty">{T.noModels}</p>}
              {textModels.map(m => (
                <AdminModelRow key={m.id} model={m} active={m.model_id === activeTextModel}
                  onSetActive={setActiveText} onDelete={mm => setConfirmDel({ kind: 'text', model: mm })} />
              ))}
            </div>
          </div>

          <div className="adm-sub">
            <div className="adm-sub-head"><span className="adm-sub-title">{T.test}</span></div>
            <textarea className="adm-textarea" rows={2} value={textTestIn} placeholder={T.testText}
              maxLength={1000} onChange={e => setTextTestIn(e.target.value)} />
            <div style={{ display: 'flex', gap: 8, alignItems: 'center', marginTop: 8 }}>
              <button type="button" className="is-btn-save" disabled={textTesting || !activeTextModel} onClick={runTextTest}>
                <i className="ti ti-sparkles"></i><span>{textTesting ? (en ? 'Generating…' : 'Genererer…') : T.generate}</span>
              </button>
            </div>
            {textTestOut && <div className="adm-output">{textTestOut}</div>}
          </div>
        </section>

        {/* ── AI Bilde ── */}
        <section className="pro-card adm-card">
          <div className="adm-card-head">
            <h2 className="adm-card-title"><i className="ti ti-photo"></i>{T.image}</h2>
            <AdmStatus msg={stImg} />
          </div>

          <div className="adm-form-row">
            <div className="is-field" style={{ flex: 1, minWidth: 180 }}>
              <label className="is-label">{T.secret}</label>
              <div style={{ display: 'flex', gap: 8 }}>
                <input className="is-input" value={imgSecret} placeholder="f.eks. RunwayAPI"
                  onChange={e => setImgSecret(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') saveImgSecret(); }} />
                <button type="button" className="is-btn-save" onClick={saveImgSecret}><i className="ti ti-check"></i><span>{T.save}</span></button>
              </div>
            </div>
          </div>

          <div className="adm-sub">
            <div className="adm-sub-head">
              <span className="adm-sub-title">{T.models}</span>
              <QuickAddNewBtn label={T.addModel} onClick={() => setAddImgOpen(true)} />
            </div>
            <div className="adm-list">
              {imgModels.length === 0 && <p className="adm-empty">{T.noModels}</p>}
              {imgModels.map(m => (
                <AdminModelRow key={m.id} model={m} active={m.model_id === activeImgModel}
                  onSetActive={setActiveImg} onDelete={mm => setConfirmDel({ kind: 'image', model: mm })} />
              ))}
            </div>
          </div>

          <div className="adm-sub">
            <div className="adm-sub-head"><span className="adm-sub-title">{T.test}</span></div>
            <textarea className="adm-textarea" rows={2} value={imgTestPrompt} placeholder={T.testImage}
              maxLength={500} onChange={e => setImgTestPrompt(e.target.value)} />
            <div style={{ display: 'flex', gap: 8, alignItems: 'center', marginTop: 8 }}>
              <button type="button" className="is-btn-save" disabled={imgTesting || !activeImgModel} onClick={runImgTest}>
                <i className="ti ti-photo-ai"></i><span>{imgTesting ? (en ? 'Generating…' : 'Genererer…') : T.generate}</span>
              </button>
            </div>
            {imgTestUrl && <img src={imgTestUrl} alt="" className="adm-img-preview" />}
          </div>
        </section>

        {/* ── Kvoter ── */}
        <section className="pro-card adm-card adm-card-wide">
          <div className="adm-card-head">
            <h2 className="adm-card-title"><i className="ti ti-gauge"></i>{T.quotas}</h2>
            <AdmStatus msg={stQuota} />
          </div>
          <div className="adm-form-row">
            <div className="is-field" style={{ flex: 1, minWidth: 200 }}>
              <label className="is-label">{T.textMonthly}</label>
              <input className="is-input" type="number" min={0} value={quotas.textMonthlyTokens}
                onChange={e => setQuotas(q => ({ ...q, textMonthlyTokens: e.target.value }))} />
            </div>
            <div className="is-field" style={{ flex: 1, minWidth: 200 }}>
              <label className="is-label">{T.imageWeekly}</label>
              <input className="is-input" type="number" min={0} value={quotas.imageWeekly}
                onChange={e => setQuotas(q => ({ ...q, imageWeekly: e.target.value }))} />
            </div>
            <div style={{ display: 'flex', alignItems: 'flex-end' }}>
              <button type="button" className="is-btn-save" onClick={saveQuotas}><i className="ti ti-check"></i><span>{T.save}</span></button>
            </div>
          </div>
          <p style={{ color: 'var(--mut)', fontSize: 12, margin: '4px 0 0' }}>
            {en ? 'Quotas apply to all paying users (and during the 7-day trial).'
                : 'Kvotene gjelder alle betalende brukere (og i 7-dagers prøveperioden).'}
          </p>
        </section>
      </div>

      <AdminAddModelModal open={addTextOpen} title={T.addModel}
        namePlaceholder="f.eks. GPT-4o Mini" idPlaceholder="f.eks. gpt-4o-mini"
        onClose={() => setAddTextOpen(false)} onSave={addTextModel} />
      <AdminAddModelModal open={addImgOpen} title={T.addModel}
        namePlaceholder="f.eks. FLUX.1 [schnell]" idPlaceholder="f.eks. civitai:618692@691639"
        onClose={() => setAddImgOpen(false)} onSave={addImgModel} />
      <AdminConfirm open={!!confirmDel}
        title={en ? 'Delete model?' : 'Slette modell?'}
        message={confirmDel ? ((en ? 'Delete ' : 'Slette ') + '“' + confirmDel.model.display_name + '”?') : ''}
        confirmLabel={en ? 'Delete' : 'Slett'} cancelLabel={en ? 'Cancel' : 'Avbryt'}
        onConfirm={confirmDelete} onCancel={() => setConfirmDel(null)} />

      <AdmStyle />
    </div>
  );
}

// Admin-spesifikk layout (grid/lister). Gjenbruker design-tokens; finner ikke opp
// nye kort-/knapp-/add-stiler (de bruker .pro-card / .is-* / QuickAddNewBtn).
function AdmStyle() {
  return (
    <style>{`
      /* KPI-tiles + skillestrek + sekjonsoverskrifter */
      .adm-section-eyebrow{font-size:11px;font-weight:700;color:var(--sec);text-transform:uppercase;letter-spacing:1.2px;margin:0 0 12px}
      .adm-hr{height:1px;max-width:980px;margin:26px 0 18px;background:linear-gradient(90deg,transparent,var(--surface-b) 12%,var(--surface-b) 88%,transparent)}
      .adm-kpis{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;max-width:980px}
      .adm-kpi{display:flex;align-items:center;gap:14px;padding:16px 18px;border:1px solid var(--surface-b);border-radius:14px;background:var(--card-bg,var(--stab-bg));box-shadow:0 1px 2px rgba(0,0,0,0.04)}
      .adm-kpi-ico{flex-shrink:0;width:42px;height:42px;border-radius:12px;display:flex;align-items:center;justify-content:center;background:rgba(0,212,170,0.1);color:var(--accent)}
      .adm-kpi-ico .ti{font-size:22px}
      .adm-kpi-main{display:flex;flex-direction:column;min-width:0;gap:1px}
      .adm-kpi-val{font-size:26px;font-weight:800;line-height:1.05;color:var(--pri);letter-spacing:-0.02em}
      .adm-kpi-lbl{font-size:12.5px;font-weight:700;color:var(--pri)}
      .adm-kpi-sub{font-size:11px;color:var(--mut)}
      .adm-kpi-bar{display:block;height:5px;margin-top:6px;border-radius:99px;background:var(--surface-b);overflow:hidden}
      .adm-kpi-bar > span{display:block;height:100%;border-radius:99px;background:linear-gradient(90deg,var(--accent),var(--accent-c,#00b4d8))}
      .adm-grid{display:grid;grid-template-columns:1fr 1fr;gap:18px;max-width:980px;align-items:start}
      .adm-card-wide{grid-column:1 / -1}
      .adm-card{gap:0}
      .adm-card-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:14px}
      .adm-card-title{display:flex;align-items:center;gap:8px;font-size:16px;font-weight:700;margin:0;color:var(--pri)}
      .adm-card-title .ti{color:var(--accent);font-size:18px}
      .adm-form-row{display:flex;flex-wrap:wrap;gap:12px;align-items:flex-end}
      .adm-sub{margin-top:18px;padding-top:16px;border-top:1px solid var(--surface-b)}
      .adm-sub-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}
      .adm-sub-title{font-size:11px;font-weight:700;color:var(--sec);text-transform:uppercase;letter-spacing:1.1px}
      .adm-list{display:flex;flex-direction:column;gap:6px}
      .adm-empty{color:var(--mut);font-size:13px;margin:2px 0}
      .adm-row{display:flex;align-items:center;gap:10px;padding:9px 12px;border:1px solid var(--surface-b);border-radius:12px;background:var(--stab-bg)}
      .adm-row-main{display:flex;flex-direction:column;min-width:0;flex:1}
      .adm-row-name{font-size:13px;font-weight:600;color:var(--pri);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
      .adm-row-id{font-size:11px;color:var(--mut);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
      .adm-pill{display:inline-flex;align-items:center;gap:5px;height:30px;padding:0 11px;border-radius:999px;border:1px solid var(--surface-b);background:transparent;color:var(--sec);font-family:var(--font);font-size:11px;font-weight:700;cursor:pointer;transition:all .15s;white-space:nowrap;flex-shrink:0}
      .adm-pill:hover{color:var(--accent);border-color:var(--accent-bd);background:rgba(0,212,170,0.06)}
      .adm-pill.is-active{color:var(--accent);border-color:var(--accent-bd);background:rgba(0,212,170,0.12);cursor:default}
      .adm-del{width:30px;height:30px;flex-shrink:0;border-radius:8px;border:1px solid var(--surface-b);background:transparent;color:var(--mut);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:all .15s}
      .adm-del:hover{color:#ff4c4c;border-color:rgba(255,76,76,0.4);background:rgba(255,76,76,0.08)}
      .adm-textarea{width:100%;border:1px solid var(--surface-b);background:rgba(255,255,255,0.04);color:var(--pri);border-radius:10px;padding:10px 12px;font-family:var(--font);font-size:14px;outline:none;resize:vertical;transition:border-color .15s}
      .adm-textarea:focus{border-color:var(--accent-bd)}
      [data-theme="light"] .adm-textarea{background:rgba(26,24,22,0.04)}
      .adm-output{margin-top:10px;padding:12px 14px;border:1px solid var(--surface-b);border-radius:10px;background:var(--stab-bg);font-size:13px;line-height:1.5;color:var(--pri);white-space:pre-wrap;word-break:break-word}
      .adm-img-preview{margin-top:10px;max-width:100%;width:256px;border-radius:12px;border:1px solid var(--surface-b);display:block}
      @media (max-width:860px){.adm-grid{grid-template-columns:1fr}.adm-kpis{grid-template-columns:1fr}}
      @media (max-width:640px){.adm-form-row{flex-direction:column;align-items:stretch}.adm-row-id{max-width:46vw}
        .adm-kpi-val{font-size:23px}}
    `}</style>
  );
}
