"use client";

import { useState, useEffect } from "react";
import { useAuth } from "@/lib/auth-context";
import api from "@/lib/api";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Separator } from "@/components/ui/separator";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
} from "@/components/ui/dialog";
import { Shield, Smartphone, Mail, Copy, Check, AlertTriangle } from "lucide-react";

interface TwoFactorStatus {
  method: "totp" | "email" | null;
  confirmed: boolean;
  enabled: boolean;
}

export function TwoFactorSettings() {
  const { refreshUser } = useAuth();
  const [status, setStatus] = useState<TwoFactorStatus | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState("");
  const [success, setSuccess] = useState("");

  // TOTP setup state
  const [totpSetup, setTotpSetup] = useState<{
    secret: string;
    qr_code_url: string;
  } | null>(null);
  const [totpCode, setTotpCode] = useState("");
  const [showTotpDialog, setShowTotpDialog] = useState(false);

  // Recovery codes state
  const [recoveryCodes, setRecoveryCodes] = useState<string[] | null>(null);
  const [showRecoveryDialog, setShowRecoveryDialog] = useState(false);
  const [copied, setCopied] = useState(false);

  // Disable state
  const [showDisableDialog, setShowDisableDialog] = useState(false);
  const [disablePassword, setDisablePassword] = useState("");

  const fetchStatus = async () => {
    try {
      const { data } = await api.get("/api/user/two-factor/status");
      setStatus(data);
    } catch {
      setError("Failed to load 2FA status.");
    } finally {
      setIsLoading(false);
    }
  };

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

  const handleEnableTotp = async () => {
    setError("");
    setSuccess("");
    try {
      const { data } = await api.post("/api/user/two-factor/totp/enable");
      setTotpSetup({ secret: data.secret, qr_code_url: data.qr_code_url });
      setShowTotpDialog(true);
    } catch {
      setError("Failed to initialize TOTP setup.");
    }
  };

  const handleConfirmTotp = async (e: React.FormEvent) => {
    e.preventDefault();
    setError("");
    try {
      const { data } = await api.post("/api/user/two-factor/totp/confirm", {
        code: totpCode,
      });
      setRecoveryCodes(data.recovery_codes);
      setShowTotpDialog(false);
      setShowRecoveryDialog(true);
      setTotpCode("");
      setTotpSetup(null);
      await fetchStatus();
      await refreshUser();
      setSuccess("Authenticator app 2FA enabled successfully.");
    } catch (err: unknown) {
      const error = err as { response?: { data?: { message?: string } } };
      setError(error.response?.data?.message || "Invalid code. Please try again.");
    }
  };

  // Email OTP setup state
  const [showEmailDialog, setShowEmailDialog] = useState(false);
  const [emailPassword, setEmailPassword] = useState("");

  const handleEnableEmail = () => {
    setError("");
    setSuccess("");
    setShowEmailDialog(true);
  };

  const handleConfirmEmail = async (e: React.FormEvent) => {
    e.preventDefault();
    setError("");
    try {
      const { data } = await api.post("/api/user/two-factor/email/enable", {
        password: emailPassword,
      });
      setRecoveryCodes(data.recovery_codes);
      setShowEmailDialog(false);
      setShowRecoveryDialog(true);
      setEmailPassword("");
      await fetchStatus();
      await refreshUser();
      setSuccess("Email OTP 2FA enabled successfully.");
    } catch (err: unknown) {
      const error = err as { response?: { data?: { message?: string } } };
      setError(error.response?.data?.message || "Failed to enable email OTP.");
    }
  };

  const handleDisable = async (e: React.FormEvent) => {
    e.preventDefault();
    setError("");
    setSuccess("");
    try {
      await api.delete("/api/user/two-factor/disable", {
        data: { password: disablePassword },
      });
      setShowDisableDialog(false);
      setDisablePassword("");
      await fetchStatus();
      await refreshUser();
      setSuccess("Two-factor authentication has been disabled.");
    } catch (err: unknown) {
      const error = err as { response?: { data?: { message?: string } } };
      setError(error.response?.data?.message || "Failed to disable 2FA.");
    }
  };

  const handleViewRecoveryCodes = async () => {
    try {
      const { data } = await api.get("/api/user/two-factor/recovery-codes");
      setRecoveryCodes(data.recovery_codes);
      setShowRecoveryDialog(true);
    } catch {
      setError("Failed to load recovery codes.");
    }
  };

  const handleRegenerateRecoveryCodes = async () => {
    try {
      const { data } = await api.post("/api/user/two-factor/recovery-codes/regenerate");
      setRecoveryCodes(data.recovery_codes);
      setSuccess("Recovery codes regenerated.");
    } catch {
      setError("Failed to regenerate recovery codes.");
    }
  };

  const copyRecoveryCodes = () => {
    if (recoveryCodes) {
      navigator.clipboard.writeText(recoveryCodes.join("\n"));
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    }
  };

  if (isLoading) {
    return (
      <Card>
        <CardContent className="flex items-center justify-center py-8">
          <p className="text-sm text-muted-foreground">Loading 2FA settings...</p>
        </CardContent>
      </Card>
    );
  }

  return (
    <>
      <Card>
        <CardHeader>
          <CardTitle className="flex items-center gap-2">
            <Shield className="h-5 w-5" />
            Two-Factor Authentication
          </CardTitle>
        </CardHeader>
        <CardContent className="space-y-4">
          {success && (
            <div className="rounded-md border border-green-200 bg-green-50 p-3 text-sm text-green-800 dark:border-green-800 dark:bg-green-950 dark:text-green-200">
              {success}
            </div>
          )}
          {error && (
            <div className="rounded-md border border-destructive/20 bg-destructive/10 p-3 text-sm text-destructive">
              {error}
            </div>
          )}

          {status?.enabled ? (
            <div className="space-y-4">
              <div className="flex items-center gap-3 rounded-lg border border-green-200 bg-green-50 p-4 dark:border-green-800 dark:bg-green-950">
                <div className="flex h-10 w-10 items-center justify-center rounded-full bg-green-100 dark:bg-green-900">
                  {status.method === "totp" ? (
                    <Smartphone className="h-5 w-5 text-green-700 dark:text-green-300" />
                  ) : (
                    <Mail className="h-5 w-5 text-green-700 dark:text-green-300" />
                  )}
                </div>
                <div>
                  <p className="font-medium text-green-800 dark:text-green-200">
                    2FA is enabled
                  </p>
                  <p className="text-sm text-green-700 dark:text-green-300">
                    {status.method === "totp"
                      ? "Using authenticator app"
                      : "Using email OTP (4-digit code)"}
                  </p>
                </div>
              </div>

              <div className="flex flex-wrap gap-2">
                <Button variant="outline" size="sm" onClick={handleViewRecoveryCodes}>
                  View Recovery Codes
                </Button>
                <Button
                  variant="destructive"
                  size="sm"
                  onClick={() => setShowDisableDialog(true)}
                >
                  Disable 2FA
                </Button>
              </div>
            </div>
          ) : (
            <div className="space-y-4">
              <p className="text-sm text-muted-foreground">
                Add an extra layer of security to your account. Choose one of the
                methods below:
              </p>

              <Separator />

              {/* Authenticator App Option */}
              <div className="flex items-start gap-4 rounded-lg border p-4">
                <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-primary/10">
                  <Smartphone className="h-5 w-5 text-primary" />
                </div>
                <div className="flex-1 space-y-1">
                  <p className="font-medium">Authenticator App</p>
                  <p className="text-sm text-muted-foreground">
                    Use an app like Google Authenticator or Authy to generate
                    time-based codes.
                  </p>
                  <Button size="sm" className="mt-2" onClick={handleEnableTotp}>
                    Enable Authenticator
                  </Button>
                </div>
              </div>

              {/* Email OTP Option */}
              <div className="flex items-start gap-4 rounded-lg border p-4">
                <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-primary/10">
                  <Mail className="h-5 w-5 text-primary" />
                </div>
                <div className="flex-1 space-y-1">
                  <p className="font-medium">Email OTP</p>
                  <p className="text-sm text-muted-foreground">
                    Receive a 4-digit verification code via email each time you
                    sign in.
                  </p>
                  <Button size="sm" className="mt-2" onClick={handleEnableEmail}>
                    Enable Email OTP
                  </Button>
                </div>
              </div>
            </div>
          )}
        </CardContent>
      </Card>

      {/* TOTP Setup Dialog */}
      <Dialog open={showTotpDialog} onOpenChange={setShowTotpDialog}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>Set Up Authenticator App</DialogTitle>
            <DialogDescription>
              Scan the QR code below with your authenticator app, then enter the
              6-digit code to confirm.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-4">
            {totpSetup && (
              <>
                <div className="flex justify-center">
                  <img
                    src={`https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(totpSetup.qr_code_url)}`}
                    alt="QR Code"
                    className="h-48 w-48 rounded-lg border"
                  />
                </div>
                <div className="space-y-2">
                  <Label className="text-xs text-muted-foreground">
                    Or enter this key manually:
                  </Label>
                  <code className="block break-all rounded bg-muted px-3 py-2 text-center text-sm font-mono">
                    {totpSetup.secret}
                  </code>
                </div>
              </>
            )}
            <form onSubmit={handleConfirmTotp} className="space-y-3">
              <div className="space-y-2">
                <Label htmlFor="totp-code">Verification Code</Label>
                <Input
                  id="totp-code"
                  type="text"
                  inputMode="numeric"
                  placeholder="000000"
                  maxLength={6}
                  value={totpCode}
                  onChange={(e) => setTotpCode(e.target.value.replace(/\D/g, ""))}
                  className="text-center text-lg tracking-widest"
                />
              </div>
              <Button type="submit" className="w-full" disabled={totpCode.length !== 6}>
                Confirm & Enable
              </Button>
            </form>
          </div>
        </DialogContent>
      </Dialog>

      {/* Email OTP Confirmation Dialog */}
      <Dialog open={showEmailDialog} onOpenChange={setShowEmailDialog}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>Enable Email OTP</DialogTitle>
            <DialogDescription>
              Enter your password to confirm enabling email OTP two-factor
              authentication.
            </DialogDescription>
          </DialogHeader>
          <form onSubmit={handleConfirmEmail} className="space-y-4">
            <div className="space-y-2">
              <Label htmlFor="email-password">Password</Label>
              <Input
                id="email-password"
                type="password"
                placeholder="Enter your password"
                value={emailPassword}
                onChange={(e) => setEmailPassword(e.target.value)}
              />
            </div>
            <Button type="submit" className="w-full" disabled={!emailPassword}>
              Confirm & Enable
            </Button>
          </form>
        </DialogContent>
      </Dialog>

      {/* Recovery Codes Dialog */}
      <Dialog open={showRecoveryDialog} onOpenChange={setShowRecoveryDialog}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>Recovery Codes</DialogTitle>
            <DialogDescription>
              Store these codes in a safe place. Each code can only be used once.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-4">
            <div className="flex items-start gap-2 rounded-md border border-amber-200 bg-amber-50 p-3 dark:border-amber-800 dark:bg-amber-950">
              <AlertTriangle className="mt-0.5 h-4 w-4 shrink-0 text-amber-600 dark:text-amber-400" />
              <p className="text-xs text-amber-800 dark:text-amber-200">
                If you lose your authenticator device, you can use these codes to
                access your account.
              </p>
            </div>
            {recoveryCodes && (
              <div className="grid grid-cols-2 gap-2 rounded-lg bg-muted p-4">
                {recoveryCodes.map((code) => (
                  <code key={code} className="text-sm font-mono">
                    {code}
                  </code>
                ))}
              </div>
            )}
            <div className="flex gap-2">
              <Button variant="outline" size="sm" onClick={copyRecoveryCodes}>
                {copied ? (
                  <Check className="mr-2 h-4 w-4" />
                ) : (
                  <Copy className="mr-2 h-4 w-4" />
                )}
                {copied ? "Copied!" : "Copy Codes"}
              </Button>
              <Button variant="outline" size="sm" onClick={handleRegenerateRecoveryCodes}>
                Regenerate
              </Button>
            </div>
          </div>
        </DialogContent>
      </Dialog>

      {/* Disable 2FA Dialog */}
      <Dialog open={showDisableDialog} onOpenChange={setShowDisableDialog}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>Disable Two-Factor Authentication</DialogTitle>
            <DialogDescription>
              Enter your password to confirm disabling 2FA.
            </DialogDescription>
          </DialogHeader>
          <form onSubmit={handleDisable} className="space-y-4">
            <div className="space-y-2">
              <Label htmlFor="disable-password">Password</Label>
              <Input
                id="disable-password"
                type="password"
                value={disablePassword}
                onChange={(e) => setDisablePassword(e.target.value)}
                placeholder="Enter your password"
              />
            </div>
            <div className="flex justify-end gap-2">
              <Button
                type="button"
                variant="outline"
                onClick={() => {
                  setShowDisableDialog(false);
                  setDisablePassword("");
                }}
              >
                Cancel
              </Button>
              <Button type="submit" variant="destructive" disabled={!disablePassword}>
                Disable 2FA
              </Button>
            </div>
          </form>
        </DialogContent>
      </Dialog>
    </>
  );
}
