"use client";

import * as React from "react";

import { useChanged } from "@/hooks/use-changed";
import { Fingerprint, KeyRound } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { requestDashboardApi } from "@/lib/dashboard-api-client";
import { toastApiError } from "@/lib/toast-api-error";
import {
  authenticatePasskeyWithOptions,
  supportsPasskeys,
} from "@/lib/passkeys/browser-client";
import type { PublicKeyCredentialRequestOptionsJSON } from "@simplewebauthn/browser";

type SessionsReauthDialogProps = {
  open: boolean;
  description?: string;
  onConfirmed: () => void | Promise<void>;
  onCancel: () => void;
};

export function SessionsReauthDialog({
  open,
  description = "Re-authenticate with your password or a passkey to end this session.",
  onConfirmed,
  onCancel,
}: SessionsReauthDialogProps) {
  const [password, setPassword] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const passkeysOk = supportsPasskeys();

  if (useChanged(open) && !open) {
    setPassword("");
    setBusy(false);
  }

  async function confirmPassword(event: React.FormEvent) {
    event.preventDefault();
    if (!password.trim() || busy) return;
    setBusy(true);
    try {
      await requestDashboardApi({
        url: "/dashboard/admins/sessions/reauth/password",
        method: "POST",
        body: { password },
        fallbackError: "Could not confirm password.",
      });
      setPassword("");
      await onConfirmed();
    } catch (error) {
      toastApiError(error, "Could not confirm password.");
    } finally {
      setBusy(false);
    }
  }

  async function confirmPasskey() {
    if (busy) return;
    setBusy(true);
    try {
      const optionsResponse = await requestDashboardApi<{
        options: PublicKeyCredentialRequestOptionsJSON;
      }>({
        url: "/dashboard/admins/sessions/reauth/passkey-options",
        method: "POST",
        body: {},
        fallbackError: "Could not start passkey confirmation.",
      });
      const credential = await authenticatePasskeyWithOptions(optionsResponse.options);
      await requestDashboardApi({
        url: "/dashboard/admins/sessions/reauth/passkey",
        method: "POST",
        body: { credential },
        fallbackError: "Could not confirm passkey.",
      });
      await onConfirmed();
    } catch (error) {
      toastApiError(error, "Could not confirm passkey.");
    } finally {
      setBusy(false);
    }
  }

  return (
    <Dialog
      open={open}
      onOpenChange={(next) => {
        if (!next && !busy) onCancel();
      }}
    >
      <DialogContent className="sm:max-w-md" showCloseButton={!busy}>
        <DialogHeader>
          <DialogTitle>Confirm it&apos;s you</DialogTitle>
          <DialogDescription>{description}</DialogDescription>
        </DialogHeader>

        <form className="space-y-3" onSubmit={(event) => void confirmPassword(event)}>
          <div className="space-y-1">
            <Label htmlFor="sessions-reauth-password">Password</Label>
            <Input
              id="sessions-reauth-password"
              type="password"
              autoComplete="current-password"
              value={password}
              onChange={(event) => setPassword(event.target.value)}
              disabled={busy}
            />
          </div>
          <Button type="submit" className="w-full" disabled={busy || !password.trim()}>
            <KeyRound className="size-4" />
            Confirm with password
          </Button>
        </form>

        {passkeysOk ? (
          <>
            <div className="text-muted-foreground text-center text-xs">or</div>
            <Button
              type="button"
              variant="outline"
              className="w-full"
              disabled={busy}
              onClick={() => void confirmPasskey()}
            >
              <Fingerprint className="size-4" />
              Confirm with passkey
            </Button>
          </>
        ) : null}

        <DialogFooter>
          <Button type="button" variant="ghost" disabled={busy} onClick={onCancel}>
            Cancel
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
