"use client"

import { useState } from "react"
import Link from "next/link"
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { z } from "zod"
import { Loader2Icon, ChevronLeftIcon, ChevronRightIcon } from "lucide-react"

import { Button } from "@/src/components/ui/button"
import { Input } from "@/src/components/ui/input"
import { PasswordField } from "@/src/components/ui/password-field"
import { Checkbox } from "@/src/components/ui/checkbox"
import PhoneInput from "@/src/components/ui/phone-input"
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/src/components/ui/form"
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
} from "@/src/components/ui/dialog"
import { LocationInput } from "@/src/components/authentication/location-input"
import OTPForm from "@/src/components/authentication/otp-form"
import {
  useRegisterRestaurantMutation,
  useResendEmailOtpMutation,
} from "@/src/state/auth"

const registrationSchema = z.object({
  email: z
    .string()
    .email("Veuillez saisir une adresse e-mail valide")
    .transform((s) => s.toLowerCase().trim()),
  password: z.string().min(6, "Le mot de passe doit contenir au moins 6 caractères"),
  restaurantName: z.string().min(1, "Le nom du restaurant est requis"),
  phoneNumber: z.string().regex(/^\+\d{8,15}$/, "Le numéro doit être au format E.164 (ex: +22676123456)"),
  address: z.string().min(1, "L'adresse est requise"),
  lat: z.number({ required_error: "La latitude est requise" }).min(-90).max(90),
  lng: z.number({ required_error: "La longitude est requise" }).min(-180).max(180),
  termsAccepted: z.boolean().refine((v) => v === true, {
    message: "Vous devez accepter les conditions d'utilisation",
  }),
})

type RegistrationValues = z.infer<typeof registrationSchema>

const STEPS = [
  { description: "Créez vos identifiants de connexion" },
  { description: "Parlez-nous de votre restaurant" },
  { description: "Sélectionnez l'emplacement de votre restaurant" },
  { description: "Acceptez les conditions et vérifiez votre e-mail" },
]

const STEP_FIELDS: (keyof RegistrationValues)[][] = [
  ["email", "password"],
  ["restaurantName", "phoneNumber"],
  ["address", "lat", "lng"],
  ["termsAccepted"],
]

export default function RegistrationForm() {
  const [step, setStep] = useState(0)
  const [otpDialogOpen, setOtpDialogOpen] = useState(false)

  const [registerRestaurant, { isLoading, error }] = useRegisterRestaurantMutation()
  const [resendEmailOtp] = useResendEmailOtpMutation()

  // @ts-expect-error error data structure
  const errorMessage = error?.data?.error_message ?? error?.data?.message

  const form = useForm<RegistrationValues>({
    resolver: zodResolver(registrationSchema),
    defaultValues: {
      email: "",
      password: "",
      restaurantName: "",
      phoneNumber: "",
      address: "",
      lat: undefined as unknown as number,
      lng: undefined as unknown as number,
      termsAccepted: false,
    },
    mode: "onTouched",
  })

  const isLastStep = step === STEPS.length - 1

  async function goNext() {
    const valid = await form.trigger(STEP_FIELDS[step])
    if (valid) setStep((s) => s + 1)
  }

  async function handleSubmit(values: RegistrationValues) {
    try {
      await registerRestaurant(values).unwrap()
      setOtpDialogOpen(true)
    } catch (error) {
      const errorResponse = error as { status?: number; data?: { message?: string; details?: { property: string; constraints: string[] }[] } }
      const data = errorResponse?.data

      if (data?.message === "Validation failed" && data?.details?.length) {
        data.details.forEach((d) => {
          form.setError(d.property as keyof RegistrationValues, {
            type: "manual",
            message: d.constraints.join(", "),
          })
        })
        return
      }

      form.setError("root", { type: "submit", message: data?.message ?? "Une erreur est survenue" })
    }
  }

  return (
    <>
      <div className="flex h-full flex-col items-center justify-center px-6 py-12">
        <div className="w-full max-w-sm space-y-8">
          <div className="space-y-1">
            <h1 className="text-2xl font-bold tracking-tight">Créer un compte</h1>
            <p className="text-sm text-muted-foreground">{STEPS[step].description}</p>
          </div>

          <div className="flex gap-1.5">
            {STEPS.map((_, i) => (
              <div
                key={i}
                className={`h-1 flex-1 rounded-full transition-colors ${
                  i <= step ? "bg-primary" : "bg-muted"
                }`}
              />
            ))}
          </div>

          <Form {...form}>
            <form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4">
              {step === 0 && (
                <>
                  <FormField
                    control={form.control}
                    name="email"
                    render={({ field }) => (
                      <FormItem>
                        <FormLabel>E-mail</FormLabel>
                        <FormControl>
                          <Input
                            type="email"
                            placeholder="vous@exemple.com"
                            disabled={isLoading}
                            {...field}
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                  <FormField
                    control={form.control}
                    name="password"
                    render={({ field }) => (
                      <FormItem>
                        <FormLabel>Mot de passe</FormLabel>
                        <FormControl>
                          <PasswordField
                            placeholder="••••••••"
                            disabled={isLoading}
                            {...field}
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                </>
              )}

              {step === 1 && (
                <>
                  <FormField
                    control={form.control}
                    name="restaurantName"
                    render={({ field }) => (
                      <FormItem>
                        <FormLabel>Nom du restaurant</FormLabel>
                        <FormControl>
                          <Input
                            placeholder="Mon Restaurant"
                            disabled={isLoading}
                            {...field}
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                  <FormField
                    control={form.control}
                    name="phoneNumber"
                    render={({ field }) => (
                      <FormItem>
                        <FormLabel>Numéro de téléphone</FormLabel>
                        <FormControl>
                          <PhoneInput
                            value={field.value}
                            onChange={field.onChange}
                            onBlur={field.onBlur}
                            disabled={isLoading}
                          />
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                </>
              )}

              {step === 2 && (
                <FormField
                  control={form.control}
                  name="address"
                  render={({ fieldState }) => (
                    <FormItem>
                      <FormLabel>Emplacement du restaurant</FormLabel>
                      <FormControl>
                        <LocationInput
                          value={
                            form.getValues("lat")
                              ? {
                                  lat: form.getValues("lat"),
                                  lng: form.getValues("lng"),
                                  address: form.getValues("address"),
                                }
                              : null
                          }
                          disabled={isLoading}
                          error={!!fieldState.error}
                          onChange={(loc) => {
                            if (loc) {
                              form.setValue("address", loc.address ?? "", { shouldValidate: true })
                              form.setValue("lat", loc.lat, { shouldValidate: true })
                              form.setValue("lng", loc.lng, { shouldValidate: true })
                            } else {
                              form.setValue("address", "")
                              form.setValue("lat", undefined as unknown as number)
                              form.setValue("lng", undefined as unknown as number)
                            }
                          }}
                        />
                      </FormControl>
                      <FormMessage />
                    </FormItem>
                  )}
                />
              )}

              {step === 3 && (
                <FormField
                  control={form.control}
                  name="termsAccepted"
                  render={({ field }) => (
                    <FormItem>
                      <div className="flex items-start gap-3">
                        <FormControl>
                          <Checkbox
                            checked={field.value}
                            onCheckedChange={field.onChange}
                            disabled={isLoading}
                          />
                        </FormControl>
                        <FormLabel className="font-normal leading-snug">
                          J&apos;accepte les{" "}
                          <Link href="/terms" className="text-primary hover:underline" target="_blank">
                            Conditions d&apos;utilisation
                          </Link>
                        </FormLabel>
                      </div>
                      <FormMessage />
                    </FormItem>
                  )}
                />
              )}

              {form.formState.errors.root && (
                <p className="text-sm text-destructive">{errorMessage}</p>
              )}

              <div className="flex gap-2 pt-2">
                {step > 0 && (
                  <Button
                    type="button"
                    variant="outline"
                    size="lg"
                    className="flex-1"
                    onClick={() => setStep((s) => s - 1)}
                    disabled={isLoading}
                  >
                    <ChevronLeftIcon />
                    Retour
                  </Button>
                )}

                {!isLastStep ? (
                  <Button
                    type="button"
                    size="lg"
                    className="flex-1"
                    onClick={goNext}
                    disabled={isLoading}
                  >
                    Suivant
                    <ChevronRightIcon />
                  </Button>
                ) : (
                  <Button
                    type="submit"
                    size="lg"
                    className="flex-1"
                    disabled={isLoading}
                  >
                    {isLoading && <Loader2Icon className="animate-spin" />}
                    Créer mon compte
                  </Button>
                )}
              </div>
            </form>
          </Form>

          <p className="text-center text-sm text-muted-foreground">
            Vous avez déjà un compte ?{" "}
            <Link href="/signin" className="font-medium text-primary hover:underline">
              Se connecter
            </Link>
          </p>
        </div>
      </div>

      <Dialog open={otpDialogOpen} onOpenChange={setOtpDialogOpen}>
        <DialogContent
          className="sm:w-auto sm:max-w-full"
          onInteractOutside={(e) => e.preventDefault()}
        >
          <DialogHeader>
            <DialogTitle>Vérifiez votre e-mail</DialogTitle>
            <DialogDescription>
              Un code de vérification a été envoyé à votre adresse e-mail. Veuillez le saisir pour activer votre compte.
            </DialogDescription>
          </DialogHeader>
          <OTPForm
            email={form.getValues("email")}
            onResend={async () => {
              await resendEmailOtp({ email: form.getValues("email") }).unwrap()
            }}
          />
        </DialogContent>
      </Dialog>
    </>
  )
}
