"use client";

import { useTransition } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import Link from "next/link";
import { signIn as clientSignIn } from "next-auth/react";
import { useForm, Controller } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Loader2, Globe } from "lucide-react";
import { toast } from "sonner";

import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Separator } from "@/components/ui/separator";
import { FormField } from "@/components/auth/form-field";
import { FormError } from "@/components/auth/form-error";
import { PasswordInput } from "@/components/auth/password-input";
import { registerAction } from "@/actions/auth-actions";
import { registerSchema, type RegisterInput } from "@/validators/auth";
import { useLanguage } from "@/lib/i18n/context";
import { safeRelativePath } from "@/emails/security";

export function RegisterForm({ googleEnabled = false }: { googleEnabled?: boolean }) {
  const router = useRouter();
  const searchParams = useSearchParams();
  const { t, locale } = useLanguage();
  const f = t.auth.form;
  const [isPending, startTransition] = useTransition();
  const [isGooglePending, startGoogleTransition] = useTransition();

  const {
    register,
    handleSubmit,
    setError,
    control,
    formState: { errors },
  } = useForm<RegisterInput>({
    resolver: zodResolver(registerSchema),
    defaultValues: {
      firstName: "",
      lastName: "",
      email: "",
      password: "",
      confirmPassword: "",
      // Zod types this as the literal `true` (it must be checked to submit),
      // so an unchecked default has to be force-cast here.
      acceptTerms: false as unknown as true,
    },
  });

  function onSubmit(values: RegisterInput) {
    const callbackUrl = searchParams.get("callbackUrl");
    const safeCallbackUrl = safeRelativePath(callbackUrl ?? undefined);

    startTransition(async () => {
      const result = await registerAction(values, locale, safeCallbackUrl);

      if (!result.success) {
        toast.error(result.error);
        if (result.fieldErrors) {
          for (const [field, messages] of Object.entries(result.fieldErrors)) {
            if (messages?.[0]) {
              setError(field as keyof RegisterInput, { message: messages[0] });
            }
          }
        }
        return;
      }

      toast.success(f.accountCreatedToast);
      const params = new URLSearchParams({ email: values.email });
      if (safeCallbackUrl) params.set("callbackUrl", safeCallbackUrl);
      router.push(`/verify-email?${params.toString()}`);
    });
  }

  function handleGoogle() {
    if (!googleEnabled) {
      toast.info(f.googleComingSoon);
      return;
    }
    const callbackUrl = searchParams.get("callbackUrl");
    startGoogleTransition(() => {
      void clientSignIn("google", {
        callbackUrl: safeRelativePath(callbackUrl ?? undefined) ?? "/dashboard",
      });
    });
  }

  return (
    <div className="flex flex-col gap-6">
      <form onSubmit={handleSubmit(onSubmit)} noValidate className="flex flex-col gap-4">
        <div className="grid grid-cols-2 gap-3">
          <FormField id="firstName" label={f.firstName} error={errors.firstName?.message}>
            <Input
              id="firstName"
              autoComplete="given-name"
              aria-invalid={!!errors.firstName}
              {...register("firstName")}
            />
          </FormField>
          <FormField id="lastName" label={f.lastName} error={errors.lastName?.message}>
            <Input
              id="lastName"
              autoComplete="family-name"
              aria-invalid={!!errors.lastName}
              {...register("lastName")}
            />
          </FormField>
        </div>

        <FormField id="email" label={f.email} error={errors.email?.message}>
          <Input
            id="email"
            type="email"
            autoComplete="email"
            aria-invalid={!!errors.email}
            {...register("email")}
          />
        </FormField>

        <FormField
          id="password"
          label={f.password}
          error={errors.password?.message}
          hint={errors.password ? undefined : f.passwordHint}
        >
          <PasswordInput
            id="password"
            autoComplete="new-password"
            aria-invalid={!!errors.password}
            {...register("password")}
          />
        </FormField>

        <FormField
          id="confirmPassword"
          label={f.confirmPassword}
          error={errors.confirmPassword?.message}
        >
          <PasswordInput
            id="confirmPassword"
            autoComplete="new-password"
            aria-invalid={!!errors.confirmPassword}
            {...register("confirmPassword")}
          />
        </FormField>

        <div className="flex flex-col gap-1.5">
          <div className="flex items-start gap-2.5">
            <Controller
              name="acceptTerms"
              control={control}
              render={({ field }) => (
                <Checkbox
                  id="acceptTerms"
                  checked={field.value === true}
                  aria-invalid={!!errors.acceptTerms}
                  onCheckedChange={(checked) => field.onChange(checked === true)}
                />
              )}
            />
            <label htmlFor="acceptTerms" className="text-sm leading-snug text-muted-foreground">
              {f.agreeToTermsPrefix}{" "}
              <Link href="/#disclaimer" className="text-foreground underline underline-offset-2">
                {f.terms}
              </Link>{" "}
              {f.and}{" "}
              <Link href="/#disclaimer" className="text-foreground underline underline-offset-2">
                {f.privacyPolicy}
              </Link>
            </label>
          </div>
          {errors.acceptTerms ? (
            <p role="alert" className="text-xs text-destructive">
              {errors.acceptTerms.message}
            </p>
          ) : null}
        </div>

        <FormError message={errors.root?.message} />

        <Button type="submit" size="lg" disabled={isPending} className="mt-2">
          {isPending ? <Loader2 className="size-4 animate-spin" /> : null}
          {f.createAccount}
        </Button>
      </form>

      <div className="flex items-center gap-3">
        <Separator className="flex-1" />
        <span className="text-xs text-muted-foreground">{f.or}</span>
        <Separator className="flex-1" />
      </div>

      <Button
        type="button"
        variant="outline"
        size="lg"
        onClick={handleGoogle}
        disabled={isGooglePending}
      >
        {isGooglePending ? <Loader2 className="size-4 animate-spin" /> : <Globe className="size-4" />}
        {f.continueWithGoogle}
      </Button>
    </div>
  );
}
