'use client';

import { useMemo, useState } from 'react';
import { useRouter } from 'next/navigation';
import { createSupabaseBrowserClient } from '@/lib/supabase/browser';
import {
  passkeyErrorMessage,
  stepUpWithPasskey,
} from '@/lib/auth/webauthn-client';

/**
 * AAL2 step-up UI: verify with TOTP or passkey, or fall back to a single-use
 * recovery code (which resets MFA and bounces the user back to /login to set up
 * a fresh factor).
 */
export function ChallengeClient({
  totpFactorId,
  passkeyFactorId,
  next,
}: {
  totpFactorId: string | null;
  passkeyFactorId: string | null;
  next: string;
}) {
  const router = useRouter();
  const supabase = useMemo(() => createSupabaseBrowserClient(), []);
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [code, setCode] = useState('');
  const [showRecovery, setShowRecovery] = useState(false);
  const [recovery, setRecovery] = useState('');

  function done() {
    router.replace(next);
    router.refresh();
  }

  async function verifyTotp(e: React.FormEvent) {
    e.preventDefault();
    if (!totpFactorId) return;
    setError(null);
    setBusy(true);
    try {
      const { data: ch, error: ce } = await supabase.auth.mfa.challenge({
        factorId: totpFactorId,
      });
      if (ce) throw ce;
      const { error: ve } = await supabase.auth.mfa.verify({
        factorId: totpFactorId,
        challengeId: ch.id,
        code: code.trim(),
      });
      if (ve) throw ve;
      done();
    } catch (e) {
      setError((e as Error).message);
      setBusy(false);
    }
  }

  async function verifyPasskey() {
    if (!passkeyFactorId) return;
    setError(null);
    setBusy(true);
    try {
      await stepUpWithPasskey(supabase, passkeyFactorId);
      done();
    } catch (e) {
      setError(passkeyErrorMessage(e));
      setBusy(false);
    }
  }

  async function redeemRecovery(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    setBusy(true);
    try {
      const res = await fetch('/api/security/recovery/redeem', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ code: recovery.trim() }),
      });
      const json = (await res.json()) as { ok?: boolean; error?: string };
      if (!res.ok || !json.ok) {
        throw new Error(
          json.error === 'invalid_code'
            ? 'That recovery code is invalid or already used.'
            : 'Recovery failed. Please try again.',
        );
      }
      // Deleting verified factors logs the user out everywhere; clear local
      // cookies and return to login to re-enroll.
      await supabase.auth.signOut().catch(() => {});
      router.replace('/login?mfa_reset=1');
      router.refresh();
    } catch (e) {
      setError((e as Error).message);
      setBusy(false);
    }
  }

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

      {passkeyFactorId && (
        <div className="card">
          <h2>Passkey</h2>
          <p className="muted">
            Verify with your device biometrics or security key.
          </p>
          <button type="button" onClick={verifyPasskey} disabled={busy}>
            {busy ? 'Waiting…' : 'Use a passkey'}
          </button>
        </div>
      )}

      {totpFactorId && (
        <div className="card">
          <h2>Authenticator app</h2>
          <form onSubmit={verifyTotp}>
            <label htmlFor="challenge-code">6-digit code</label>
            <input
              id="challenge-code"
              type="text"
              inputMode="numeric"
              autoComplete="one-time-code"
              pattern="[0-9]*"
              maxLength={6}
              required
              value={code}
              onChange={(e) => setCode(e.target.value)}
            />
            <div className="row" style={{ marginTop: '1rem' }}>
              <button type="submit" disabled={busy || code.trim().length < 6}>
                {busy ? 'Verifying…' : 'Verify'}
              </button>
            </div>
          </form>
        </div>
      )}

      <div className="card">
        <h2>Lost access?</h2>
        {showRecovery ? (
          <form onSubmit={redeemRecovery}>
            <p className="muted">
              Enter a recovery code. This removes your current two-factor
              methods so you can set up new ones after signing in again.
            </p>
            <label htmlFor="recovery-code">Recovery code</label>
            <input
              id="recovery-code"
              type="text"
              autoComplete="off"
              placeholder="xxxx-xxxx-xxxx"
              required
              value={recovery}
              onChange={(e) => setRecovery(e.target.value)}
            />
            <div className="row" style={{ marginTop: '1rem' }}>
              <button
                type="submit"
                className="btn-danger"
                disabled={busy || recovery.trim().length === 0}
              >
                {busy ? 'Working…' : 'Use recovery code'}
              </button>
            </div>
          </form>
        ) : (
          <button
            type="button"
            className="secondary"
            onClick={() => setShowRecovery(true)}
            disabled={busy}
          >
            Use a recovery code
          </button>
        )}
      </div>
    </div>
  );
}
