"use client";

import { useState, useEffect } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Checkbox } from "@/components/ui/checkbox";
import {
    Form,
    FormControl,
    FormField,
    FormItem,
    FormLabel,
    FormMessage
} from "@/components/ui/form";
import { Card, CardContent, CardHeader } from "@/components/ui/card";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import Link from "next/link";
import { Progress } from "@/components/ui/progress";
import { SignUpResponse } from "@server/routers/auth";
import { useRouter } from "next/navigation";
import { passwordSchema } from "@server/auth/passwordSchema";
import { AxiosResponse } from "axios";
import { formatAxiosError } from "@app/lib/api";
import { createApiClient } from "@app/lib/api";
import { useEnvContext } from "@app/hooks/useEnvContext";
import { cleanRedirect } from "@app/lib/cleanRedirect";
import { useTranslations } from "next-intl";
import BrandingLogo from "@app/components/BrandingLogo";
import { build } from "@server/build";
import { Check, X } from "lucide-react";
import { cn } from "@app/lib/cn";
import { useLicenseStatusContext } from "@app/hooks/useLicenseStatusContext";

// Password strength calculation
const calculatePasswordStrength = (password: string) => {
    const requirements = {
        length: password.length >= 8,
        uppercase: /[A-Z]/.test(password),
        lowercase: /[a-z]/.test(password),
        number: /[0-9]/.test(password),
        special: /[~!`@#$%^&*()_\-+={}[\]|\\:;"'<>,.\/?]/.test(password)
    };

    const score = Object.values(requirements).filter(Boolean).length;
    let strength: "weak" | "medium" | "strong" = "weak";
    let color = "bg-red-500";
    let percentage = 0;

    if (score >= 5) {
        strength = "strong";
        color = "bg-green-500";
        percentage = 100;
    } else if (score >= 3) {
        strength = "medium";
        color = "bg-yellow-500";
        percentage = 60;
    } else if (score >= 1) {
        strength = "weak";
        color = "bg-red-500";
        percentage = 30;
    }

    return { requirements, strength, color, percentage, score };
};

type SignupFormProps = {
    redirect?: string;
    inviteId?: string;
    inviteToken?: string;
    emailParam?: string;
    fromSmartLogin?: boolean;
    skipVerificationEmail?: boolean;
};

const formSchema = z
    .object({
        email: z.string().email({ message: "Invalid email address" }),
        password: passwordSchema,
        confirmPassword: passwordSchema,
        agreeToTerms: z.boolean().refine(
            (val) => {
                if (build === "saas") {
                    val === true;
                }
                return true;
            },
            {
                message:
                    "You must agree to the terms of service and privacy policy"
            }
        ),
        marketingEmailConsent: z.boolean().optional()
    })
    .refine((data) => data.password === data.confirmPassword, {
        path: ["confirmPassword"],
        message: "Passwords do not match"
    });

export default function SignupForm({
    redirect,
    inviteId,
    inviteToken,
    emailParam,
    fromSmartLogin = false,
    skipVerificationEmail = false
}: SignupFormProps) {
    const router = useRouter();
    const { env } = useEnvContext();
    const api = createApiClient({ env });
    const t = useTranslations();
    const { isUnlocked } = useLicenseStatusContext();

    const [loading, setLoading] = useState(false);
    const [error, setError] = useState<string | null>(null);
    const [termsAgreedAt, setTermsAgreedAt] = useState<string | null>(null);
    const [passwordValue, setPasswordValue] = useState("");
    const [confirmPasswordValue, setConfirmPasswordValue] = useState("");

    const form = useForm({
        resolver: zodResolver(formSchema),
        defaultValues: {
            email: emailParam || "",
            password: "",
            confirmPassword: "",
            agreeToTerms: false,
            marketingEmailConsent: false
        },
        mode: "onChange" // Enable real-time validation
    });

    const passwordStrength = calculatePasswordStrength(passwordValue);
    const doPasswordsMatch =
        passwordValue.length > 0 &&
        confirmPasswordValue.length > 0 &&
        passwordValue === confirmPasswordValue;

    async function onSubmit(values: z.infer<typeof formSchema>) {
        const { email, password, marketingEmailConsent } = values;

        setLoading(true);
        const res = await api
            .put<AxiosResponse<SignUpResponse>>("/auth/signup", {
                email,
                password,
                inviteId,
                inviteToken,
                termsAcceptedTimestamp: termsAgreedAt,
                marketingEmailConsent:
                    build === "saas" ? marketingEmailConsent : undefined,
                skipVerificationEmail: skipVerificationEmail || undefined
            })
            .catch((e) => {
                console.error(e);
                setError(formatAxiosError(e, t("signupError")));
            });

        if (res && res.status === 200) {
            setError(null);

            if (res.data?.data?.emailVerificationRequired) {
                if (redirect) {
                    const safe = cleanRedirect(redirect);
                    router.push(`/auth/verify-email?redirect=${safe}`);
                } else {
                    router.push("/auth/verify-email");
                }
                return;
            }

            if (redirect) {
                const safe = cleanRedirect(redirect);
                router.push(safe);
            } else {
                router.push("/");
            }
        }

        setLoading(false);
    }

    function getSubtitle() {
        if (isUnlocked() && env.branding?.signupPage?.subtitleText) {
            return env.branding.signupPage.subtitleText;
        }
        return t("authCreateAccount");
    }

    const handleTermsChange = (checked: boolean) => {
        if (checked) {
            const isoNow = new Date().toISOString();
            console.log("Terms agreed at:", isoNow);
            setTermsAgreedAt(isoNow);
            form.setValue("agreeToTerms", true);
        } else {
            form.setValue("agreeToTerms", false);
            setTermsAgreedAt(null);
        }
    };

    const logoWidth = isUnlocked()
        ? env.branding.logo?.authPage?.width || 175
        : 175;
    const logoHeight = isUnlocked()
        ? env.branding.logo?.authPage?.height || 44
        : 44;

    const showOrgBanner =
        fromSmartLogin &&
        (build === "saas" || env.app.identityProviderMode === "org");
    const orgBannerHref = redirect
        ? `/auth/org?redirect=${encodeURIComponent(redirect)}`
        : "/auth/org";

    return (
        <>
            {showOrgBanner && (
                <Alert className="mb-4 w-full max-w-md">
                    <AlertTitle>{t("signupOrgNotice")}</AlertTitle>
                    <AlertDescription className="space-y-2 mt-3">
                        <p>{t("signupOrgTip")}</p>
                        <Link
                            href={orgBannerHref}
                            className="text-sm font-medium underline"
                        >
                            {t("signupOrgLink")}
                        </Link>
                    </AlertDescription>
                </Alert>
            )}
            <Card className="w-full max-w-md">
                <CardHeader className="border-b">
                    <div className="flex flex-row items-center justify-center">
                        <BrandingLogo height={logoHeight} width={logoWidth} />
                    </div>
                    <div className="text-center space-y-1 pt-3">
                        <p className="text-muted-foreground">{getSubtitle()}</p>
                    </div>
                </CardHeader>
                <CardContent className="pt-6">
                    <Form {...form}>
                        <form
                            onSubmit={form.handleSubmit(onSubmit)}
                            className="space-y-4"
                        >
                            <FormField
                                control={form.control}
                                name="email"
                                render={({ field }) => (
                                    <FormItem>
                                        <FormLabel>{t("email")}</FormLabel>
                                        <FormControl>
                                            <Input
                                                {...field}
                                                disabled={!!emailParam}
                                            />
                                        </FormControl>
                                        <FormMessage />
                                    </FormItem>
                                )}
                            />
                            <FormField
                                control={form.control}
                                name="password"
                                render={({ field }) => (
                                    <FormItem>
                                        <div className="flex items-center gap-2">
                                            <FormLabel>
                                                {t("password")}
                                            </FormLabel>
                                            {passwordStrength.strength ===
                                                "strong" && (
                                                <Check className="h-4 w-4 text-green-500" />
                                            )}
                                        </div>
                                        <FormControl>
                                            <div className="relative">
                                                <Input
                                                    type="password"
                                                    {...field}
                                                    onChange={(e) => {
                                                        field.onChange(e);
                                                        setPasswordValue(
                                                            e.target.value
                                                        );
                                                    }}
                                                    className={cn(
                                                        passwordStrength.strength ===
                                                            "strong" &&
                                                            "border-green-500 focus-visible:ring-green-500",
                                                        passwordStrength.strength ===
                                                            "medium" &&
                                                            "border-yellow-500 focus-visible:ring-yellow-500",
                                                        passwordStrength.strength ===
                                                            "weak" &&
                                                            passwordValue.length >
                                                                0 &&
                                                            "border-red-500 focus-visible:ring-red-500"
                                                    )}
                                                    autoComplete="new-password"
                                                />
                                            </div>
                                        </FormControl>

                                        {passwordValue.length > 0 && (
                                            <div className="space-y-3 mt-2">
                                                {/* Password Strength Meter */}
                                                <div className="space-y-2">
                                                    <div className="flex justify-between items-center">
                                                        <span className="text-sm font-medium text-foreground">
                                                            {t(
                                                                "passwordStrength"
                                                            )}
                                                        </span>
                                                        <span
                                                            className={cn(
                                                                "text-sm font-semibold",
                                                                passwordStrength.strength ===
                                                                    "strong" &&
                                                                    "text-green-600 dark:text-green-400",
                                                                passwordStrength.strength ===
                                                                    "medium" &&
                                                                    "text-yellow-600 dark:text-yellow-400",
                                                                passwordStrength.strength ===
                                                                    "weak" &&
                                                                    "text-red-600 dark:text-red-400"
                                                            )}
                                                        >
                                                            {t(
                                                                `passwordStrength${passwordStrength.strength.charAt(0).toUpperCase() + passwordStrength.strength.slice(1)}`
                                                            )}
                                                        </span>
                                                    </div>
                                                    <Progress
                                                        value={
                                                            passwordStrength.percentage
                                                        }
                                                        className="h-2"
                                                    />
                                                </div>

                                                {/* Requirements Checklist */}
                                                <div className="bg-muted rounded-lg p-3 space-y-2">
                                                    <div className="text-sm font-medium text-foreground mb-2">
                                                        {t(
                                                            "passwordRequirements"
                                                        )}
                                                    </div>
                                                    <div className="grid grid-cols-1 gap-1.5">
                                                        <div className="flex items-center gap-2">
                                                            {passwordStrength
                                                                .requirements
                                                                .length ? (
                                                                <Check className="h-3.5 w-3.5 text-green-500 flex-shrink-0" />
                                                            ) : (
                                                                <X className="h-3.5 w-3.5 text-muted-foreground flex-shrink-0" />
                                                            )}
                                                            <span
                                                                className={cn(
                                                                    "text-sm",
                                                                    passwordStrength
                                                                        .requirements
                                                                        .length
                                                                        ? "text-green-600 dark:text-green-400"
                                                                        : "text-muted-foreground"
                                                                )}
                                                            >
                                                                {t(
                                                                    "passwordRequirementLengthText"
                                                                )}
                                                            </span>
                                                        </div>
                                                        <div className="flex items-center gap-2">
                                                            {passwordStrength
                                                                .requirements
                                                                .uppercase ? (
                                                                <Check className="h-3.5 w-3.5 text-green-500 flex-shrink-0" />
                                                            ) : (
                                                                <X className="h-3.5 w-3.5 text-muted-foreground flex-shrink-0" />
                                                            )}
                                                            <span
                                                                className={cn(
                                                                    "text-sm",
                                                                    passwordStrength
                                                                        .requirements
                                                                        .uppercase
                                                                        ? "text-green-600 dark:text-green-400"
                                                                        : "text-muted-foreground"
                                                                )}
                                                            >
                                                                {t(
                                                                    "passwordRequirementUppercaseText"
                                                                )}
                                                            </span>
                                                        </div>
                                                        <div className="flex items-center gap-2">
                                                            {passwordStrength
                                                                .requirements
                                                                .lowercase ? (
                                                                <Check className="h-3.5 w-3.5 text-green-500 flex-shrink-0" />
                                                            ) : (
                                                                <X className="h-3.5 w-3.5 text-muted-foreground flex-shrink-0" />
                                                            )}
                                                            <span
                                                                className={cn(
                                                                    "text-sm",
                                                                    passwordStrength
                                                                        .requirements
                                                                        .lowercase
                                                                        ? "text-green-600 dark:text-green-400"
                                                                        : "text-muted-foreground"
                                                                )}
                                                            >
                                                                {t(
                                                                    "passwordRequirementLowercaseText"
                                                                )}
                                                            </span>
                                                        </div>
                                                        <div className="flex items-center gap-2">
                                                            {passwordStrength
                                                                .requirements
                                                                .number ? (
                                                                <Check className="h-3.5 w-3.5 text-green-500 flex-shrink-0" />
                                                            ) : (
                                                                <X className="h-3.5 w-3.5 text-muted-foreground flex-shrink-0" />
                                                            )}
                                                            <span
                                                                className={cn(
                                                                    "text-sm",
                                                                    passwordStrength
                                                                        .requirements
                                                                        .number
                                                                        ? "text-green-600 dark:text-green-400"
                                                                        : "text-muted-foreground"
                                                                )}
                                                            >
                                                                {t(
                                                                    "passwordRequirementNumberText"
                                                                )}
                                                            </span>
                                                        </div>
                                                        <div className="flex items-center gap-2">
                                                            {passwordStrength
                                                                .requirements
                                                                .special ? (
                                                                <Check className="h-3.5 w-3.5 text-green-500 flex-shrink-0" />
                                                            ) : (
                                                                <X className="h-3.5 w-3.5 text-muted-foreground flex-shrink-0" />
                                                            )}
                                                            <span
                                                                className={cn(
                                                                    "text-sm",
                                                                    passwordStrength
                                                                        .requirements
                                                                        .special
                                                                        ? "text-green-600 dark:text-green-400"
                                                                        : "text-muted-foreground"
                                                                )}
                                                            >
                                                                {t(
                                                                    "passwordRequirementSpecialText"
                                                                )}
                                                            </span>
                                                        </div>
                                                    </div>
                                                </div>
                                            </div>
                                        )}

                                        {/* Only show FormMessage when not showing our custom requirements */}
                                        {passwordValue.length === 0 && (
                                            <FormMessage />
                                        )}
                                    </FormItem>
                                )}
                            />
                            <FormField
                                control={form.control}
                                name="confirmPassword"
                                render={({ field }) => (
                                    <FormItem>
                                        <div className="flex items-center gap-2">
                                            <FormLabel>
                                                {t("confirmPassword")}
                                            </FormLabel>
                                            {doPasswordsMatch && (
                                                <Check className="h-4 w-4 text-green-500" />
                                            )}
                                        </div>
                                        <FormControl>
                                            <div className="relative">
                                                <Input
                                                    type="password"
                                                    {...field}
                                                    onChange={(e) => {
                                                        field.onChange(e);
                                                        setConfirmPasswordValue(
                                                            e.target.value
                                                        );
                                                    }}
                                                    className={cn(
                                                        doPasswordsMatch &&
                                                            "border-green-500 focus-visible:ring-green-500",
                                                        confirmPasswordValue.length >
                                                            0 &&
                                                            !doPasswordsMatch &&
                                                            "border-red-500 focus-visible:ring-red-500"
                                                    )}
                                                    autoComplete="new-password"
                                                />
                                            </div>
                                        </FormControl>
                                        {confirmPasswordValue.length > 0 &&
                                            !doPasswordsMatch && (
                                                <p className="text-sm text-red-600 mt-1">
                                                    {t("passwordsDoNotMatch")}
                                                </p>
                                            )}
                                        {/* Only show FormMessage when field is empty */}
                                        {confirmPasswordValue.length === 0 && (
                                            <FormMessage />
                                        )}
                                    </FormItem>
                                )}
                            />
                            {build === "saas" && (
                                <>
                                    <FormField
                                        control={form.control}
                                        name="agreeToTerms"
                                        render={({ field }) => (
                                            <FormItem className="flex flex-row items-center">
                                                <FormControl>
                                                    <Checkbox
                                                        checked={field.value}
                                                        onCheckedChange={(
                                                            checked
                                                        ) => {
                                                            field.onChange(
                                                                checked
                                                            );
                                                            handleTermsChange(
                                                                checked as boolean
                                                            );
                                                        }}
                                                    />
                                                </FormControl>
                                                <div className="leading-none">
                                                    <FormLabel className="text-sm font-normal">
                                                        <div>
                                                            {t(
                                                                "signUpTerms.IAgreeToThe"
                                                            )}{" "}
                                                            <a
                                                                href="https://pangolin.net/tos"
                                                                target="_blank"
                                                                rel="noopener noreferrer"
                                                                className="text-primary hover:underline"
                                                            >
                                                                {t(
                                                                    "signUpTerms.termsOfService"
                                                                )}{" "}
                                                            </a>
                                                            {t(
                                                                "signUpTerms.and"
                                                            )}{" "}
                                                            <a
                                                                href="https://pangolin.net/privacy"
                                                                target="_blank"
                                                                rel="noopener noreferrer"
                                                                className="text-primary hover:underline"
                                                            >
                                                                {t(
                                                                    "signUpTerms.privacyPolicy"
                                                                )}
                                                            </a>
                                                        </div>
                                                    </FormLabel>
                                                    <FormMessage />
                                                </div>
                                            </FormItem>
                                        )}
                                    />
                                    <FormField
                                        control={form.control}
                                        name="marketingEmailConsent"
                                        render={({ field }) => (
                                            <FormItem className="flex flex-row items-start">
                                                <FormControl>
                                                    <Checkbox
                                                        checked={field.value}
                                                        onCheckedChange={
                                                            field.onChange
                                                        }
                                                    />
                                                </FormControl>
                                                <div className="leading-none">
                                                    <FormLabel className="text-sm font-normal">
                                                        {t(
                                                            "signUpMarketing.keepMeInTheLoop"
                                                        )}
                                                    </FormLabel>
                                                    <FormMessage />
                                                </div>
                                            </FormItem>
                                        )}
                                    />
                                </>
                            )}

                            {error && (
                                <Alert variant="destructive">
                                    <AlertDescription>{error}</AlertDescription>
                                </Alert>
                            )}

                            <Button type="submit" className="w-full">
                                {t("createAccount")}
                            </Button>
                        </form>
                    </Form>
                </CardContent>
            </Card>
        </>
    );
}
