'use client';

import { useEffect, useState } from 'react';
import { apiFetch } from '@/lib/api';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/cn';

interface KeyRow {
  version: number;
  active: boolean;
  createdAt: string;
  retiredAt: string | null;
}

interface Status {
  activeVersion: number | null;
  keyCount: number;
  secretCount: number;
  legacySecretCount: number;
  keys: KeyRow[];
}

export default function AdminEncryptionPage() {
  const [status, setStatus] = useState<Status | null>(null);
  const [rotating, setRotating] = useState(false);
  const [message, setMessage] = useState<string | null>(null);

  async function reload() {
    setStatus(await apiFetch<Status>('/v1/admin/encryption'));
  }

  useEffect(() => {
    reload();
  }, []);

  async function rotate() {
    if (
      !confirm(
        'Rotate the encryption key?\n\nA fresh Data Encryption Key is generated and EVERY stored secret is re-encrypted under it in one transaction. The environment KEK is untouched. This is safe to run any time you suspect key compromise.',
      )
    ) {
      return;
    }
    setRotating(true);
    setMessage(null);
    try {
      const r = await apiFetch<{ newVersion: number; reEncrypted: number }>(
        '/v1/admin/encryption/rotate',
        { method: 'POST', body: '{}' },
      );
      setMessage(`Rotated to key v${r.newVersion} — ${r.reEncrypted} secret(s) re-encrypted.`);
      await reload();
    } catch (e) {
      const detail = (e as { detail?: { detail?: string; error?: string } }).detail;
      setMessage(`Rotation failed: ${detail?.detail ?? detail?.error ?? (e as Error).message}`);
    } finally {
      setRotating(false);
    }
  }

  return (
    <div className="px-8 py-8">
      <header className="mb-6">
        <h1 className="text-[22px] font-semibold tracking-tight">Encryption</h1>
        <p className="mt-1 text-[13px] text-[--color-fg-muted]">
          Envelope encryption for customer secrets. The KEK lives only in the environment;
          Data Encryption Keys are stored wrapped and rotated here.
        </p>
      </header>

      {!status && <div className="mono text-[12px] text-[--color-fg-muted]">Loading…</div>}

      {status && (
        <>
          <div className="grid gap-3 md:grid-cols-3">
            <Card label="Active key" value={status.activeVersion ? `v${status.activeVersion}` : '—'} />
            <Card label="Secrets encrypted" value={status.secretCount.toLocaleString()} />
            <Card
              label="Legacy (pre-envelope)"
              value={status.legacySecretCount.toLocaleString()}
              sub={
                status.legacySecretCount > 0
                  ? 'rotate once to migrate them onto a DEK'
                  : 'all on a managed DEK'
              }
            />
          </div>

          <div className="panel mt-6 p-4">
            <div className="flex items-baseline justify-between">
              <div>
                <h2 className="text-[14px] font-semibold tracking-tight">Rotate encryption key</h2>
                <p className="mt-1 text-[12.5px] leading-relaxed text-[--color-fg-muted]">
                  Generates a new DEK and re-encrypts all {status.secretCount} secret(s) under it
                  atomically. The environment KEK is never exposed or changed.
                </p>
              </div>
              <Button variant="primary" size="md" onClick={rotate} disabled={rotating}>
                {rotating ? 'Rotating…' : 'Rotate key'}
              </Button>
            </div>
            {message && (
              <p
                className={cn(
                  'mt-3 text-[12.5px]',
                  message.startsWith('Rotation failed')
                    ? 'text-[--color-danger]'
                    : 'text-emerald-300',
                )}
              >
                {message}
              </p>
            )}
          </div>

          <div className="mt-6">
            <h2 className="text-[14px] font-semibold tracking-tight">Key history</h2>
            <div className="panel mt-3">
              <table className="w-full text-[12.5px]">
                <thead className="border-b border-[--color-border] text-[--color-fg-subtle]">
                  <tr>
                    <th className="px-4 py-2 text-left font-medium">Version</th>
                    <th className="px-4 py-2 text-left font-medium">Status</th>
                    <th className="px-4 py-2 text-left font-medium">Created</th>
                    <th className="px-4 py-2 text-left font-medium">Retired</th>
                  </tr>
                </thead>
                <tbody>
                  {status.keys.map((k) => (
                    <tr key={k.version} className="border-b border-[--color-border] last:border-0">
                      <td className="px-4 py-2.5 mono">v{k.version}</td>
                      <td className="px-4 py-2.5">
                        <span
                          className={cn(
                            'mono rounded-full border px-2 py-0.5 text-[11px]',
                            k.active
                              ? 'border-emerald-400/40 bg-emerald-400/10 text-emerald-300'
                              : 'border-[--color-border] bg-[--color-bg-subtle] text-[--color-fg-subtle]',
                          )}
                        >
                          {k.active ? 'active' : 'retired'}
                        </span>
                      </td>
                      <td className="px-4 py-2.5 mono text-[--color-fg-muted]">
                        {new Date(k.createdAt).toLocaleString()}
                      </td>
                      <td className="px-4 py-2.5 mono text-[--color-fg-muted]">
                        {k.retiredAt ? new Date(k.retiredAt).toLocaleString() : '—'}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>

          <p className="mt-6 text-[11.5px] leading-relaxed text-[--color-fg-subtle]">
            How it works: a 32-byte Data Encryption Key (DEK) is generated, AES-256-GCM encrypted
            with the environment Key Encryption Key (KEK = SECRETS_ENCRYPTION_KEY), and stored
            wrapped. Secrets are encrypted with the DEK. Rotation mints a fresh DEK, re-encrypts
            every secret, and retires the old one — recoverable from a suspected DEK compromise
            without ever touching the KEK.
          </p>
        </>
      )}
    </div>
  );
}

function Card({ label, value, sub }: { label: string; value: string; sub?: string }) {
  return (
    <div className="panel p-4">
      <div className="text-[11px] uppercase tracking-wider text-[--color-fg-subtle]">{label}</div>
      <div className="mt-1.5 text-[24px] font-semibold tabular-nums tracking-tight">{value}</div>
      {sub && <div className="mt-1 text-[12px] text-[--color-fg-muted]">{sub}</div>}
    </div>
  );
}
