'use client';

import { useMemo, useState } from 'react';
import { useRouter } from 'next/navigation';
import { createSupabaseBrowserClient } from '@/lib/supabase/browser';
import {
  PasskeyEnrollPanel,
  RecoveryCodesPanel,
  TotpEnrollPanel,
} from './mfa-components';

type FactorView = {
  id: string;
  type: string;
  friendlyName: string | null;
  createdAt: string;
};

const TYPE_LABEL: Record<string, string> = {
  totp: 'Authenticator app',
  webauthn: 'Passkey',
  phone: 'Phone',
};

/**
 * Security settings client: list verified factors, add new ones, remove
 * factors (never the last one — mandatory MFA), and regenerate recovery codes.
 */
export function SecurityClient({
  initialFactors,
}: {
  initialFactors: FactorView[];
}) {
  const router = useRouter();
  const supabase = useMemo(() => createSupabaseBrowserClient(), []);
  const [factors] = useState<FactorView[]>(initialFactors);
  const [adding, setAdding] = useState<null | 'totp' | 'webauthn'>(null);
  const [busyId, setBusyId] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [notice, setNotice] = useState<string | null>(null);
  const [codes, setCodes] = useState<string[] | null>(null);
  const [regenBusy, setRegenBusy] = useState(false);

  async function remove(id: string) {
    if (factors.length <= 1) {
      setError('You must keep at least one two-factor method enabled.');
      return;
    }
    setError(null);
    setNotice(null);
    setBusyId(id);
    try {
      const res = await fetch('/api/security/unenroll', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ factorId: id }),
      });
      if (!res.ok) {
        const json = (await res.json().catch(() => null)) as {
          error?: string;
        } | null;
        if (json?.error === 'cannot_remove_last_factor') {
          throw new Error('You must keep at least one two-factor method enabled.');
        }
        throw new Error(json?.error || 'Could not remove this method.');
      }
      router.refresh();
    } catch (e) {
      setError((e as Error).message);
    } finally {
      setBusyId(null);
    }
  }

  function onAdded() {
    setAdding(null);
    setNotice('Two-factor method added.');
    router.refresh();
  }

  async function regenerate() {
    setError(null);
    setNotice(null);
    setCodes(null);
    setRegenBusy(true);
    try {
      const res = await fetch('/api/security/recovery/generate', {
        method: 'POST',
      });
      const json = (await res.json()) as { codes?: string[]; error?: string };
      if (!res.ok || !json.codes) {
        throw new Error(json.error || 'Could not generate recovery codes.');
      }
      setCodes(json.codes);
    } catch (e) {
      setError((e as Error).message);
    } finally {
      setRegenBusy(false);
    }
  }

  return (
    <div className="stack">
      {error && <p className="error">{error}</p>}
      {notice && <p className="success">{notice}</p>}

      <div className="card">
        <h2>Your two-factor methods</h2>
        {factors.length === 0 ? (
          <p className="muted">No methods enabled.</p>
        ) : (
          <table className="admin-table">
            <thead>
              <tr>
                <th>Method</th>
                <th>Name</th>
                <th>Added</th>
                <th aria-label="actions" />
              </tr>
            </thead>
            <tbody>
              {factors.map((f) => (
                <tr key={f.id}>
                  <td>{TYPE_LABEL[f.type] ?? f.type}</td>
                  <td>{f.friendlyName ?? '—'}</td>
                  <td>{new Date(f.createdAt).toLocaleDateString()}</td>
                  <td>
                    <button
                      type="button"
                      className="btn-sm btn-danger"
                      onClick={() => remove(f.id)}
                      disabled={busyId === f.id || factors.length <= 1}
                      title={
                        factors.length <= 1
                          ? 'At least one method is required'
                          : 'Remove this method'
                      }
                    >
                      {busyId === f.id ? 'Removing…' : 'Remove'}
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>

      {adding === 'totp' && (
        <TotpEnrollPanel supabase={supabase} onVerified={onAdded} />
      )}
      {adding === 'webauthn' && (
        <PasskeyEnrollPanel supabase={supabase} onVerified={onAdded} />
      )}

      {adding === null && (
        <div className="card">
          <h2>Add a method</h2>
          <div className="row">
            <button type="button" onClick={() => setAdding('totp')}>
              Add authenticator app
            </button>
            <button
              type="button"
              className="secondary"
              onClick={() => setAdding('webauthn')}
            >
              Add passkey
            </button>
          </div>
        </div>
      )}

      <div className="card">
        <h2>Recovery codes</h2>
        <p className="muted">
          Generate a new set of single-use recovery codes. This invalidates any
          codes you were issued before.
        </p>
        {codes && <RecoveryCodesPanel codes={codes} />}
        <div className="row" style={{ marginTop: '1rem' }}>
          <button
            type="button"
            className="secondary"
            onClick={regenerate}
            disabled={regenBusy}
          >
            {regenBusy ? 'Generating…' : 'Regenerate recovery codes'}
          </button>
        </div>
      </div>
    </div>
  );
}
