'use client';

import { useState, useEffect, useCallback } from 'react';
import { Fingerprint, Loader2, AlertCircle, Trash2, Plus, Laptop, Usb } from 'lucide-react';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { apiFetch } from '@/lib/api';

interface Passkey {
  id: string;
  friendlyName: string;
  deviceType: 'platform' | 'cross-platform';
  backedUp: boolean;
  lastUsedAt: string | null;
  createdAt: string;
}

interface PasskeyRegistrationOptions {
  challenge: string;
  user: { id: string; name: string; displayName: string };
  rp: { name: string; id: string };
  pubKeyCredParams: { type: string; alg: number }[];
  excludeCredentials: { id: string; type: string }[];
  [key: string]: unknown;
}

export default function PasskeyManagementPage() {
  const [passkeys, setPasskeys] = useState<Passkey[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [registering, setRegistering] = useState(false);

  const fetchPasskeys = useCallback(async () => {
    setLoading(true);
    setError('');
    const { data, error: err } = await apiFetch<Passkey[]>('/auth/passkeys');
    if (data) {
      setPasskeys(data);
    } else {
      setError(err || 'Failed to load passkeys');
    }
    setLoading(false);
  }, []);

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

  const handleRegister = async () => {
    setRegistering(true);
    setError('');
    try {
      // Step 1: Get registration options from server
      const { data: options, error: optErr } = await apiFetch<PasskeyRegistrationOptions>(
        '/auth/passkeys/register/options',
        { method: 'POST' }
      );
      if (!options || optErr) {
        setError(optErr || 'Failed to start passkey registration');
        return;
      }

      // Step 2: Create credential via WebAuthn API
      if (!window.PublicKeyCredential) {
        setError('Passkeys are not supported in this browser');
        return;
      }

      // Convert base64url fields to ArrayBuffer for WebAuthn API
      const publicKeyOptions: PublicKeyCredentialCreationOptions = {
        challenge: base64urlToBuffer(options.challenge),
        rp: options.rp,
        user: {
          id: base64urlToBuffer(options.user.id),
          name: options.user.name,
          displayName: options.user.displayName,
        },
        pubKeyCredParams: options.pubKeyCredParams as PublicKeyCredentialParameters[],
        excludeCredentials: (options.excludeCredentials || []).map(cred => ({
          id: base64urlToBuffer(cred.id),
          type: cred.type as PublicKeyCredentialType,
        })),
      };

      const credential = (await navigator.credentials.create({
        publicKey: publicKeyOptions,
      })) as PublicKeyCredential;

      if (!credential) {
        setError('Passkey creation was cancelled');
        return;
      }

      // Step 3: Send credential response to server for verification
      const attestationResponse = credential.response as AuthenticatorAttestationResponse;
      const { error: verifyErr } = await apiFetch<{ id: string }>(
        '/auth/passkeys/register/verify',
        {
          method: 'POST',
          body: JSON.stringify({
            id: credential.id,
            rawId: bufferToBase64url(credential.rawId),
            type: credential.type,
            response: {
              clientDataJSON: bufferToBase64url(attestationResponse.clientDataJSON),
              attestationObject: bufferToBase64url(attestationResponse.attestationObject),
            },
          }),
        }
      );

      if (verifyErr) {
        setError(verifyErr || 'Passkey registration failed');
        return;
      }

      await fetchPasskeys();
    } catch (err) {
      if (err instanceof DOMException && err.name === 'NotAllowedError') {
        setError('Passkey creation was cancelled or timed out');
      } else {
        setError('Passkey registration failed');
      }
    } finally {
      setRegistering(false);
    }
  };

  const handleDelete = async (id: string) => {
    if (!confirm('Remove this passkey? You will no longer be able to sign in with it.')) return;
    const { error: delErr } = await apiFetch<{ success: boolean }>(`/auth/passkeys/${id}`, {
      method: 'DELETE',
    });
    if (!delErr) {
      setPasskeys(prev => prev.filter(p => p.id !== id));
    } else {
      setError(delErr || 'Failed to remove passkey');
    }
  };

  if (loading) {
    return (
      <div className="flex items-center justify-center py-12">
        <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
      </div>
    );
  }

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-bold tracking-tight">Passkeys</h1>
          <p className="text-muted-foreground">
            Sign in with biometrics or a security key — no password needed
          </p>
        </div>
        <Button onClick={handleRegister} disabled={registering}>
          {registering ? (
            <Loader2 className="mr-2 h-4 w-4 animate-spin" />
          ) : (
            <Plus className="mr-2 h-4 w-4" />
          )}
          Add passkey
        </Button>
      </div>

      {error && (
        <div className="flex items-center gap-2 rounded-md bg-destructive/10 p-3 text-sm text-destructive">
          <AlertCircle className="h-4 w-4 shrink-0" />
          {error}
        </div>
      )}

      {passkeys.length === 0 ? (
        <Card>
          <CardContent className="py-12 text-center">
            <Fingerprint className="mx-auto h-12 w-12 text-muted-foreground mb-4" />
            <p className="text-muted-foreground">No passkeys registered yet</p>
            <p className="text-xs text-muted-foreground mt-1">
              Passkeys use biometrics (Face ID, Touch ID, Windows Hello) or a security key for
              passwordless login.
            </p>
          </CardContent>
        </Card>
      ) : (
        <div className="grid gap-4">
          {passkeys.map(pk => (
            <Card key={pk.id}>
              <CardHeader>
                <div className="flex items-center justify-between">
                  <div className="flex items-center gap-3">
                    <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-muted">
                      {pk.deviceType === 'platform' ? (
                        <Laptop className="h-5 w-5 text-muted-foreground" />
                      ) : (
                        <Usb className="h-5 w-5 text-muted-foreground" />
                      )}
                    </div>
                    <div>
                      <CardTitle className="text-base">{pk.friendlyName || 'Passkey'}</CardTitle>
                      <CardDescription>
                        {pk.deviceType === 'platform' ? 'Built-in authenticator' : 'Security key'}
                        {pk.backedUp && ' · Synced'}
                      </CardDescription>
                    </div>
                  </div>
                  <Button variant="ghost" size="sm" onClick={() => handleDelete(pk.id)}>
                    <Trash2 className="h-4 w-4 text-destructive" />
                  </Button>
                </div>
              </CardHeader>
              <CardContent>
                <div className="flex gap-6 text-xs text-muted-foreground">
                  <div>Created: {new Date(pk.createdAt).toLocaleDateString()}</div>
                  {pk.lastUsedAt && (
                    <div>Last used: {new Date(pk.lastUsedAt).toLocaleDateString()}</div>
                  )}
                </div>
              </CardContent>
            </Card>
          ))}
        </div>
      )}
    </div>
  );
}

// ── WebAuthn helpers ──────────────────────────────────────────

function base64urlToBuffer(base64url: string): ArrayBuffer {
  const base64 = base64url.replace(/-/g, '+').replace(/_/g, '/');
  const padded = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), '=');
  const binary = atob(padded);
  const bytes = new Uint8Array(binary.length);
  for (let i = 0; i < binary.length; i++) {
    bytes[i] = binary.charCodeAt(i);
  }
  return bytes.buffer;
}

function bufferToBase64url(buffer: ArrayBuffer): string {
  const bytes = new Uint8Array(buffer);
  let binary = '';
  for (let i = 0; i < bytes.length; i++) {
    binary += String.fromCharCode(bytes[i]);
  }
  return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}
