"use client";
import { Button } from "@/components/ui/button";
import { Form, FormControl, FormField, FormItem, FormMessage, useZodForm } from "@/components/ui/form";
import { InputOTP, InputOTPGroup, InputOTPSlot } from "@/components/ui/input-otp";
import { Input } from "@/components/ui/input";
import { useMutation } from "@tanstack/react-query";
import { Smartphone, Loader2, FileKey2 } from "lucide-react";
import { toast } from "sonner";
import { BackupCodeSchema, OtpSchema, OtpSchemaType } from "./2fa.schema";
import { authClient } from "@/lib/auth/auth-client";
import { useState } from "react";

type TwoFactorFormProps = {
    onSuccess?: (success: boolean) => void;
    onSuccessData?: (data: any) => void;
};

export default function TwoFactorForm({ onSuccess, onSuccessData }: TwoFactorFormProps) {

    const [isBackupCodeMode, setIsBackupCodeMode] = useState(false);

    const otpForm = useZodForm({
        schema: isBackupCodeMode ? BackupCodeSchema : OtpSchema,
        defaultValues: {
            code: "",
        },
    });

    const { mutate: verifyOtp, isPending: isVerifyingOtp } = useMutation({
        mutationFn: async (values: OtpSchemaType) => {
            const { data, error } = await authClient.twoFactor.verifyTotp({
                code: values.code,
            });
            if (error) throw error;
            return data;
        },
        onSuccess: (data) => {
            toast.success("Authentication successful.");
            onSuccess?.(true);
            onSuccessData?.(data);
        },
        onError: (_e) => {
            toast.error("Incorrect or expired code.");
            otpForm.reset();
            onSuccess?.(false);
        },
    });

    const { mutate: verifyBackupCode, isPending: isVerifyingBackupCode } = useMutation({
        mutationFn: async (values: OtpSchemaType) => {
            const { data, error } = await authClient.twoFactor.verifyBackupCode({
                code: values.code,
            });
            if (error) throw error;
            return data;
        },
        onSuccess: (data) => {
            toast.success("Backup code accepted successfully.");
            onSuccess?.(true);
            onSuccessData?.(data);
        },
        onError: (_e) => {
            toast.error("Invalid backup code.");
            otpForm.reset();
            onSuccess?.(false);
        },
    });

    const handleSubmit = async (values: OtpSchemaType) => {
        if (isBackupCodeMode) {
            verifyBackupCode(values);
        } else {
            verifyOtp(values);
        }
    };

    const isPending = isVerifyingOtp || isVerifyingBackupCode;



    return (
        <Form form={otpForm} onSubmit={handleSubmit}>
            <div className="space-y-6 py-4">
                <div className="flex flex-col items-center justify-center gap-4 text-center">
                    <div className="p-3 bg-neutral-50 text-neutral-600 rounded-full transition-all duration-300">
                        {isBackupCodeMode ? <FileKey2 className="w-8 h-8 text-amber-600" /> : <Smartphone className="w-8 h-8" />}
                    </div>
                    <div className="space-y-1 animate-in fade-in slide-in-from-bottom-2 duration-300">
                        <h4 className="font-medium text-sm">{isBackupCodeMode ? "Backup Code Authentication" : "Device Authentication"}</h4>
                        <p className="text-xs text-muted-foreground max-w-[250px] mx-auto">
                            {isBackupCodeMode ? "Please enter one of your backup codes." : "\"Please enter the verification code generated by your authentication app.\""}
                        </p>
                    </div>
                </div>

                <FormField
                    control={otpForm.control}
                    name="code"
                    render={({ field }) => (
                        <FormItem className="flex flex-col items-center">
                            <FormControl>
                                {isBackupCodeMode ? (
                                    <Input
                                        {...field}
                                        placeholder="XXXXX-XXXXX"
                                        className="text-center tracking-widest font-mono"
                                        autoComplete="off"
                                        autoFocus
                                        onChange={(e) => {
                                            const value = e.target.value;
                                            field.onChange(value);
                                            if (value.replaceAll("-", "").length === 10) {
                                                handleSubmit({ code: value });
                                            }
                                        }}
                                    />
                                ) : (
                                    <InputOTP
                                        maxLength={6}
                                        {...field}
                                        autoFocus
                                        onChange={(value) => {
                                            field.onChange(value);
                                            if (value.length === 6) {
                                                handleSubmit({ code: value });
                                            }
                                        }}
                                    >
                                        <InputOTPGroup>
                                            <InputOTPSlot index={0} className="uppercase" />
                                            <InputOTPSlot index={1} className="uppercase" />
                                            <InputOTPSlot index={2} className="uppercase" />
                                            <InputOTPSlot index={3} className="uppercase" />
                                            <InputOTPSlot index={4} className="uppercase" />
                                            <InputOTPSlot index={5} className="uppercase" />
                                        </InputOTPGroup>
                                    </InputOTP>
                                )}
                            </FormControl>
                            <FormMessage />
                        </FormItem>
                    )}
                />

                <div className="flex flex-col gap-3 pt-2">
                    <Button type="submit" className="h-11" disabled={isPending}>
                        {isPending && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
                        Verify
                    </Button>

                    <Button
                        type="button"
                        variant="link"
                        className="text-xs text-muted-foreground hover:text-foreground h-auto p-0"
                        onClick={() => {
                            otpForm.reset();
                            setIsBackupCodeMode(!isBackupCodeMode);
                        }}
                    >
                        {isBackupCodeMode ? "Use Authentication App" : "Use Backup Code"}
                    </Button>
                </div>
            </div>
        </Form>
    );
}
