import { differenceInYears, format } from "date-fns";
import { enUS, it } from "date-fns/locale";
import { CalendarIcon } from "lucide-react";
import { type Control, useWatch } from "react-hook-form";
import toast from "react-hot-toast";
import { z } from "zod/v4";
import {
	Form,
	FormControl,
	FormField,
	FormItem,
	FormLabel,
	FormMessage,
} from "~/components/custom_ui/form";
import { MultiSelect } from "~/components/custom_ui/multiselect";
import { Button } from "~/components/ui/button";
import { Calendar } from "~/components/ui/calendar";
import Input from "~/components/ui/input";
import {
	Popover,
	PopoverContent,
	PopoverTrigger,
} from "~/components/ui/popover";
import { Separator } from "~/components/ui/separator";
import {
	getProvinciaFromSigla,
	ITALY_CATASTO_CODE,
	parseDBComune,
	parseDBNazione,
} from "~/lib/catasto";
import {
	checkFiscalCodeValidity,
	NullableStringOnChange,
} from "~/lib/form_utils";
import { cn } from "~/lib/utils";
import { useZodForm } from "~/lib/zodForm";
import { useCatasto } from "~/providers/CatastoProvider";
import { useTranslation } from "~/providers/I18nProvider";
import type { CompleteUserData } from "~/server/services/user.service";
import { api } from "~/utils/api";

const profileFormSchema = z.object({
	cap_residenza: z.string().optional(),
	civico_residenza: z.string().optional(),
	codice_fiscale: z.string().optional(),
	comune_residenza: z.string().nullable(),
	data_nascita: z.date().optional(),
	luogo_nascita: z.string().nullable(),
	nazione_nascita: z.string().nullable(),
	nazione_residenza: z.string().nullable(),
	provincia_residenza: z.string().nullable(),
	sesso: z.string().optional(),
	via_residenza: z.string().optional(),
});

type ProfileFormValues = z.infer<typeof profileFormSchema>;
export const ProfileFormAnagrafica = ({
	userData,
}: {
	userData: CompleteUserData;
}) => {
	const { comuni, nazioni } = useCatasto();

	const schema = profileFormSchema.superRefine(
		(
			{
				data_nascita,
				codice_fiscale,
				sesso,
				luogo_nascita,
				nazione_nascita,
				cap_residenza,
			},
			refinementContext,
		) => {
			if (cap_residenza) {
				if (cap_residenza.length !== 5) {
					refinementContext.issues.push({
						code: "custom",
						input: "",
						message: "Inserisci un CAP valido",
					});
				}
			}

			if (data_nascita) {
				const diff = differenceInYears(data_nascita, new Date());
				if (diff === 0) {
					refinementContext.issues.push({
						code: "custom",
						input: "",
						message: "Inserisci una data valida",
						path: ["data_nascita"],
					});
				}
			}
			if (
				codice_fiscale &&
				codice_fiscale.length > 0 &&
				data_nascita &&
				sesso &&
				luogo_nascita &&
				nazione_nascita
			) {
				checkFiscalCodeValidity({
					codiceFiscale: codice_fiscale,
					cognome: userData.cognome?.toUpperCase() || "",
					dataNascita: data_nascita,
					luogoNascita: luogo_nascita,
					nazioneNascita: nazione_nascita,
					nome: userData.nome?.toUpperCase() || "",
					path: "codice_fiscale",
					refinementContext,
					sesso,
					comuneCatasto: comuni.find((c) => c.catasto === luogo_nascita),
					nazioneCatasto: nazioni.find((c) => c.catasto === nazione_nascita),
				});
			}
		},
	);

	const defaultValues: ProfileFormValues = {
		cap_residenza: userData.cap_residenza || "",
		civico_residenza: userData.civico_residenza || "",
		codice_fiscale: userData.codice_fiscale || "",
		comune_residenza: userData.comune_residenza,
		data_nascita: userData.data_nascita || new Date(),
		luogo_nascita: userData.luogo_nascita,
		nazione_nascita: userData.nazione_nascita,
		nazione_residenza: userData.nazione_residenza,
		provincia_residenza: userData.provincia_residenza,
		sesso: userData.sesso || "",
		via_residenza: userData.via_residenza || "",
	};
	const { locale, t } = useTranslation();
	const DatePickerLocale = locale === "it" ? it : enUS;
	z.config(z.locales[locale]());

	const form = useZodForm(schema, {
		defaultValues: defaultValues,
	});

	const utils = api.useUtils();

	const { mutate } = api.users.editUserAnagrafica.useMutation({
		onError: (error) => {
			toast.error(error.message);
		},
		onSuccess: async () => {
			toast.success(t.profile.aggiornato);
			await utils.auth.getSession.invalidate();
			await utils.users.getUser.invalidate();
			await utils.users.getClientProfilo.invalidate({
				userId: userData.id,
			});
		},
	});

	function onSubmit(fields: ProfileFormValues) {
		mutate({
			userId: userData.id,
			data: { ...fields },
		});
	}

	return (
		<>
			<Form {...form}>
				{/* <FormDebug control={form.control} /> */}
				<form
					className="h-full space-y-8 px-0.5"
					onSubmit={form.handleSubmit(onSubmit)}
				>
					<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
						<FormField
							control={form.control}
							name="data_nascita"
							render={({ field }) => (
								<FormItem className="flex w-full flex-col">
									<div className="flex flex-wrap items-center gap-x-2">
										<FormLabel htmlFor="data_nascita">
											{t.anagrafica.dataNascita}
										</FormLabel>
										<FormMessage />
									</div>
									<Popover>
										<PopoverTrigger asChild>
											<FormControl>
												<Button
													className={cn(
														"h-10 w-full bg-card pl-3 text-left font-medium",
														!field.value && "text-muted-foreground",
														"rounded-lg border border-neutral-300 shadow-xs outline-hidden file:border-0 file:bg-transparent file:font-medium file:text-sm disabled:cursor-not-allowed disabled:opacity-50 dark:focus:border-transparent",
													)}
													id="data_nascita"
													variant={"outline"}
												>
													{field.value ? (
														format(field.value, "PPP", {
															locale: DatePickerLocale,
														})
													) : (
														<span>{t.anagrafica.scegli_data}</span>
													)}
													<CalendarIcon className="ml-auto size-4 opacity-50" />
												</Button>
											</FormControl>
										</PopoverTrigger>
										<PopoverContent align="end" className="w-auto p-0">
											<Calendar
												autoFocus
												captionLayout="dropdown"
												defaultMonth={field.value}
												endMonth={new Date()}
												locale={DatePickerLocale}
												mode="single"
												onSelect={field.onChange}
												selected={field.value}
											/>
										</PopoverContent>
									</Popover>
								</FormItem>
							)}
						/>

						<FormField
							control={form.control}
							name="nazione_nascita"
							render={({ field }) => {
								const parsedNazioneNascita = parseDBNazione(
									field.value,
									nazioni,
								);
								return (
									<FormItem className="w-full">
										<div className="flex flex-wrap items-center gap-x-2">
											<FormLabel htmlFor="select-naz">
												{t.anagrafica.nazioneNascita}
											</FormLabel>
											<FormMessage />
										</div>

										<FormControl>
											<MultiSelect
												defaultValue={
													field.value
														? parsedNazioneNascita
															? {
																	label: parsedNazioneNascita.nome,
																	value: parsedNazioneNascita.catasto,
																}
															: {
																	label: field.value,
																	value: field.value,
																}
														: undefined
												}
												elementId="select-naz"
												elementName="nazione_nascita"
												isMulti={false}
												onValueChange={async (value) => {
													field.onChange(value.value);
													await form.trigger("luogo_nascita");
													form.setValue("luogo_nascita", null);
												}}
												options={nazioni.map((n) => ({
													label: n.nome,
													value: n.catasto,
												}))}
												placeholder="Seleziona..."
											/>
										</FormControl>
									</FormItem>
								);
							}}
						/>

						<FormField
							control={form.control}
							name="luogo_nascita"
							render={({ field }) => {
								if (form.watch("nazione_nascita") === ITALY_CATASTO_CODE) {
									const parsedComuneNascita = parseDBComune(
										field.value,
										comuni,
									);
									return (
										<FormItem className="w-full">
											<div className="flex flex-wrap items-center gap-x-2">
												<FormLabel htmlFor="select-comune">
													{t.anagrafica.luogoNascita}
												</FormLabel>
												<FormMessage />
											</div>

											<FormControl>
												<MultiSelect
													defaultValue={
														field.value && parsedComuneNascita
															? {
																	label: `${parsedComuneNascita.nome} (${parsedComuneNascita.sigla})`,
																	value: parsedComuneNascita.catasto,
																}
															: undefined
													}
													elementId="select-comune"
													elementName="luogo_nascita"
													isMulti={false}
													onValueChange={async (value) => {
														field.onChange(value.value);
														await form.trigger("luogo_nascita");
														await form.trigger("codice_fiscale");
													}}
													options={comuni.map((c) => ({
														label: `${c.nome} (${c.sigla})`,
														value: c.catasto,
													}))}
													placeholder="Seleziona..."
												/>
											</FormControl>
										</FormItem>
									);
								}
								return (
									<FormItem className="w-full">
										<div className="flex flex-wrap items-center gap-x-2">
											<FormLabel htmlFor="luogoNascita">
												{t.anagrafica.luogoNascita}
											</FormLabel>
											<FormMessage />
										</div>
										<FormControl>
											<Input
												{...field}
												id="luogoNascita"
												onChange={async (e) => {
													NullableStringOnChange(e, field.onChange);

													await form.trigger("luogo_nascita");
													await form.trigger("codice_fiscale");
												}}
												type="text"
												value={field.value || ""}
											/>
										</FormControl>
									</FormItem>
								);
							}}
						/>
					</div>
					<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
						<FormField
							control={form.control}
							name="sesso"
							render={({ field }) => (
								<FormItem className="w-full">
									<div className="flex flex-wrap items-center gap-x-2">
										<FormLabel htmlFor="select-sesso">
											{t.anagrafica.sesso}
										</FormLabel>
										<FormMessage />
									</div>
									<MultiSelect
										defaultValue={t.anagrafica.sesso_options.filter(
											(v) => v.value === field.value,
										)}
										elementId="select-sesso"
										elementName="sesso"
										isMulti={false}
										onValueChange={async (value) => {
											field.onChange(value.value);
											await form.trigger("codice_fiscale");
										}}
										options={t.anagrafica.sesso_options}
										placeholder=""
									/>
								</FormItem>
							)}
						/>

						<FormField
							control={form.control}
							name="codice_fiscale"
							render={({ field }) => (
								<FormItem className="w-full">
									<div className="flex flex-wrap items-center gap-x-2">
										<FormLabel htmlFor="codice_fiscale">
											{t.anagrafica.codiceFiscale}
										</FormLabel>
										<FormMessage />
									</div>
									<FormControl>
										<Input
											{...field}
											className="uppercase"
											id="codice_fiscale"
											maxLength={16}
											onChange={async (v) => {
												field.onChange(v.target.value.toUpperCase());
												await form.trigger("codice_fiscale");
											}}
											type="text"
										/>
									</FormControl>
								</FormItem>
							)}
						/>
					</div>

					<Separator />

					<ResidenzaSection
						control={form.control}
						setValue={form.setValue}
						trigger={form.trigger}
					/>

					<Button type="submit">{t.profile.aggiorna}</Button>
				</form>
			</Form>
		</>
	);
};

const ResidenzaSection = ({
	control,
	setValue,
	trigger,
}: {
	control: Control<ProfileFormValues>;
	// biome-ignore lint/suspicious/noExplicitAny: <fine here>
	setValue: (field: keyof ProfileFormValues, value: any) => void;
	trigger: (name?: keyof ProfileFormValues) => Promise<boolean>;
}) => {
	const { comuni, nazioni, provincie } = useCatasto();
	const { t } = useTranslation();

	const nazione_residenza = useWatch({
		control: control,
		name: "nazione_residenza",
	});
	const provincia_residenza = useWatch({
		control: control,
		name: "provincia_residenza",
	});

	return (
		<>
			<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
				<FormField
					control={control}
					name="nazione_residenza"
					render={({ field }) => {
						const parsedNazioneResidenza = parseDBNazione(field.value, nazioni);
						return (
							<FormItem className="w-full">
								<div className="flex flex-wrap items-center gap-x-2">
									<FormLabel htmlFor="nazione_residenza">
										{t.recapiti.nazione}
									</FormLabel>
									<FormMessage />
								</div>
								<MultiSelect
									defaultValue={
										field.value
											? parsedNazioneResidenza
												? {
														label: parsedNazioneResidenza.nome,
														value: parsedNazioneResidenza.catasto,
													}
												: {
														label: field.value,
														value: field.value,
													}
											: undefined
									}
									elementId="nazione_residenza"
									elementName="nazione"
									isMulti={false}
									onValueChange={async (value) => {
										setValue("provincia_residenza", null);
										setValue("comune_residenza", null);
										field.onChange(value.value);
										await trigger("comune_residenza");
									}}
									options={nazioni.map((n) => ({
										label: n.nome,
										value: n.catasto,
									}))}
									placeholder="Seleziona"
								/>
							</FormItem>
						);
					}}
				/>

				<FormField
					control={control}
					name="provincia_residenza"
					render={({ field }) => {
						const parseProvincia = getProvinciaFromSigla(
							field.value,
							provincie,
						);
						return (
							<FormItem className="w-full">
								<div className="flex flex-wrap items-center gap-x-2">
									<FormLabel htmlFor="provincia_residenza">
										{t.recapiti.provincia}
									</FormLabel>
									<FormMessage />
								</div>

								{nazione_residenza === ITALY_CATASTO_CODE ? (
									<MultiSelect
										defaultValue={
											field.value && parseProvincia
												? {
														label: parseProvincia.nome,
														value: parseProvincia.sigla,
													}
												: undefined
										}
										elementId="provincia_residenza"
										elementName="provincia"
										isMulti={false}
										onValueChange={(value) => {
											field.onChange(value.value);
											setValue("comune_residenza", null);
										}}
										options={provincie.map((prov) => ({
											label: prov.nome,
											value: prov.sigla,
										}))}
										placeholder="Seleziona"
									/>
								) : (
									<FormControl>
										<Input
											{...field}
											id="provincia_residenza"
											type="text"
											value={field.value || undefined}
										/>
									</FormControl>
								)}
							</FormItem>
						);
					}}
				/>
			</div>
			<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
				<FormField
					control={control}
					name="comune_residenza"
					render={({ field }) => {
						if (nazione_residenza === ITALY_CATASTO_CODE) {
							const parsedComuneResidenza = parseDBComune(field.value, comuni);

							const options = comuni
								.filter((comune) =>
									provincia_residenza
										? comune.sigla === provincia_residenza
										: true,
								)
								.map((comune) => ({
									label: comune.nome,
									value: comune.catasto,
								}));

							return (
								<FormItem className="w-full">
									<div className="flex flex-wrap items-center gap-x-2">
										<FormLabel htmlFor="select-comune-residenza">
											{t.recapiti.comune}
										</FormLabel>
										<FormMessage />
									</div>

									<FormControl>
										<MultiSelect
											defaultValue={
												field.value && parsedComuneResidenza
													? {
															label: parsedComuneResidenza.nome,
															value: parsedComuneResidenza.catasto,
														}
													: undefined
											}
											elementId="select-comune-residenza"
											elementName="comune_residenza"
											isMulti={false}
											onValueChange={async (value) => {
												field.onChange(value.value);
												await trigger("comune_residenza");
												const selectedComune = comuni.find(
													(c) => c.catasto === value.value,
												);
												if (selectedComune?.cap) {
													setValue("cap_residenza", selectedComune.cap);
												}
											}}
											options={options}
											placeholder="Seleziona..."
										/>
									</FormControl>
								</FormItem>
							);
						}
						return (
							<FormItem className="w-full">
								<div className="flex w-full flex-wrap items-center gap-x-2">
									<FormLabel htmlFor="comune_residenza">
										{t.recapiti.comune}
									</FormLabel>
									<FormMessage />
								</div>
								<FormControl>
									<Input
										{...field}
										className="w-full"
										id="comune_residenza"
										onChange={async (v) => {
											field.onChange(v.target.value);
											await trigger("comune_residenza");
										}}
										type="text"
										value={field.value || undefined}
									/>
								</FormControl>
							</FormItem>
						);
					}}
				/>

				<FormField
					control={control}
					name="cap_residenza"
					render={({ field }) => (
						<FormItem className="w-full">
							<div className="flex flex-wrap items-center gap-x-2">
								<FormLabel htmlFor="cap_residenza">{t.recapiti.cap}</FormLabel>

								<FormMessage />
							</div>
							<FormControl>
								<Input
									{...field}
									id="cap_residenza"
									placeholder=""
									type="text"
								/>
							</FormControl>
						</FormItem>
					)}
				/>
			</div>
			<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
				<FormField
					control={control}
					name="via_residenza"
					render={({ field }) => (
						<FormItem className="w-full">
							<div className="flex flex-wrap items-center gap-x-2">
								<FormLabel htmlFor="via_residenza">
									{t.recapiti.indirizzo}
								</FormLabel>
								<FormMessage />
							</div>
							<FormControl>
								<Input
									{...field}
									id="via_residenza"
									placeholder="Via ..."
									type="text"
								/>
							</FormControl>
						</FormItem>
					)}
				/>

				<FormField
					control={control}
					name="civico_residenza"
					render={({ field }) => (
						<FormItem className="w-full">
							<div className="flex flex-wrap items-center gap-x-2">
								<FormLabel htmlFor="civico_residenza">
									{t.recapiti.civico}
								</FormLabel>

								<FormMessage />
							</div>
							<FormControl>
								<Input
									{...field}
									id="civico_residenza"
									placeholder=""
									type="text"
								/>
							</FormControl>
						</FormItem>
					)}
				/>
			</div>
		</>
	);
};
