import { useState } from "react";
import { Smartphone } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Field, FieldError } from "@/components/ui/field";
import { InputGroup, InputGroupInput } from "@/components/ui/input-group";
import { Label } from "@/components/ui/label";
import { cn } from "@/lib/utils";
import type { ReactNode } from "react";

// ─── Types ────────────────────────────────────────────────────────────────────

export type TwoFAApp = {
  name: string;
  icon?: ReactNode;
  qrNode?: ReactNode;
};

export type TwoFASetupFormProps = {
  title?: string;
  apps?: TwoFAApp[];
  qrCodeNode?: ReactNode;
  onVerify: (token: string) => Promise<void>;
  onSetupLater?: () => void;
  required?: boolean;
  className?: string;
};

const DEFAULT_APPS: TwoFAApp[] = [
  { name: "Google Authenticator" },
  { name: "Microsoft Authenticator" },
];

const STEP_META = {
  1: {
    subtitle: "We recommend Google Authenticator or Microsoft Authenticator",
    defaultTitle: "2FA Setup",
  },
  2: {
    title: "Open Auth App and Scan Code",
    subtitle: "Open your authenticator app and scan the QR code",
  },
} as const;

// ─── AppDownloadStep ─────────────────────────────────────────────────────────

function AppDownloadStep({
  apps,
  onNext,
  onSetupLater,
  required,
}: {
  apps: TwoFAApp[];
  onNext: () => void;
  onSetupLater?: () => void;
  required?: boolean;
}) {
  return (
    <div className="flex flex-col gap-6">
      <div className="flex flex-col gap-3">
        {apps.map((app) => (
          <div
            key={app.name}
            className="flex items-center gap-4 border border-border bg-muted/30 p-4"
          >
            <div className="flex shrink-0 items-center justify-center">
              {app.qrNode ?? (
                <div className="flex h-[80px] w-[80px] items-center justify-center border border-dashed border-border bg-muted/50 text-[11px] text-muted-foreground">
                  Scan
                </div>
              )}
            </div>
            <div className="flex flex-col gap-1">
              <div className="flex items-center gap-2 text-sm font-medium text-foreground">
                {app.icon ?? (
                  <Smartphone size={16} className="text-muted-foreground" />
                )}
                {app.name}
              </div>
              <p className="text-xs text-muted-foreground">Scan to download</p>
            </div>
          </div>
        ))}
      </div>

      <p className="text-center text-sm text-muted-foreground">
        Once downloaded, or if you already have the app installed, click Next.
      </p>

      <div className="flex flex-col gap-2">
        <Button className="w-full" onClick={onNext}>
          Next
        </Button>
        {!required && onSetupLater && (
          <Button variant="ghost" className="w-full" onClick={onSetupLater}>
            Setup Later
          </Button>
        )}
      </div>
    </div>
  );
}

// ─── VerificationStep ────────────────────────────────────────────────────────

function VerificationStep({
  qrCodeNode,
  onVerify,
  onBack,
  onSetupLater,
  required,
}: {
  qrCodeNode?: ReactNode;
  onVerify: (token: string) => Promise<void>;
  onBack: () => void;
  onSetupLater?: () => void;
  required?: boolean;
}) {
  const [token, setToken] = useState("");
  const [error, setError] = useState("");
  const [isLoading, setIsLoading] = useState(false);

  const handleVerify = async () => {
    if (!token) {
      setError("Required");
      return;
    }
    setError("");
    setIsLoading(true);
    try {
      await onVerify(token);
    } catch (err) {
      setError(
        err instanceof Error ? err.message : "Invalid code. Please try again."
      );
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <div className="flex flex-col gap-6">
      <div className="flex flex-col items-center gap-3">
        {qrCodeNode ?? (
          <div className="flex h-[140px] w-[140px] items-center justify-center border border-dashed border-border bg-muted/50 text-xs text-muted-foreground">
            QR Code
          </div>
        )}
        <p className="text-center text-sm text-muted-foreground">
          The temporary code will show for authentication. Insert below.
        </p>
      </div>

      <Field>
        <Label htmlFor="2fa-token">Verification Code</Label>
        <InputGroup>
          <InputGroupInput
            id="2fa-token"
            type="text"
            name="token"
            placeholder="Enter Your Code"
            value={token}
            aria-invalid={!!error}
            onChange={(e) => {
              setToken(e.target.value);
              if (error) setError("");
            }}
            onKeyDown={(e) => {
              if (e.key === "Enter") handleVerify();
            }}
          />
        </InputGroup>
        {error && <FieldError>{error}</FieldError>}
      </Field>

      <div className="flex flex-col gap-2">
        <Button
          loading={isLoading}
          disabled={!token}
          className="w-full"
          onClick={handleVerify}
        >
          Verify Now
        </Button>
        <Button variant="outline" className="w-full" onClick={onBack}>
          Back
        </Button>
        {!required && onSetupLater && (
          <Button variant="ghost" className="w-full" onClick={onSetupLater}>
            Setup Later
          </Button>
        )}
      </div>
    </div>
  );
}

// ─── TwoFASetupForm ───────────────────────────────────────────────────────────

export function TwoFASetupForm({
  title,
  apps = DEFAULT_APPS,
  qrCodeNode,
  onVerify,
  onSetupLater,
  required = true,
  className,
}: TwoFASetupFormProps) {
  const [step, setStep] = useState<1 | 2>(1);

  const stepTitle =
    step === 1 ? title ?? STEP_META[1].defaultTitle : STEP_META[2].title;
  const stepSubtitle = STEP_META[step].subtitle;

  return (
    <div className={cn("flex flex-col gap-6", className)}>
      <div className="flex flex-col items-center gap-1 text-center">
        <h2 className="text-xl font-semibold text-foreground">{stepTitle}</h2>
        <p className="text-sm text-muted-foreground">{stepSubtitle}</p>
      </div>

      {step === 1 ? (
        <AppDownloadStep
          apps={apps}
          onNext={() => setStep(2)}
          onSetupLater={onSetupLater}
          required={required}
        />
      ) : (
        <VerificationStep
          qrCodeNode={qrCodeNode}
          onVerify={onVerify}
          onBack={() => setStep(1)}
          onSetupLater={onSetupLater}
          required={required}
        />
      )}
    </div>
  );
}
