import { format, isAfter } from "date-fns";
import { it } from "date-fns/locale";
import { ChevronDownIcon } from "lucide-react";
import { useEffect } from "react";
import { useFormContext, useWatch } from "react-hook-form";
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 { useZodForm } from "~/lib/zodForm";
import {
	type MailsTemplates,
	TemplateKeys,
	Templates,
	type TemplateType,
} from "~/server/services/mail-templates";



type FormProps = {
	submitMutation: (values: {
		lock_expires: Date;
		template: MailsTemplates;
		subject: string;
	}) => void;
};

const Schema = z
	.object({
		expires_date: z.date().refine((d) => isAfter(d, new Date()) || d.toDateString() === new Date().toDateString(), {
			message: "La data deve essere nel futuro o oggi",
		}),
		expires_time: z.string(),
		mailType: z.enum(TemplateKeys),
		mailProps: z.record(z.string(), z.unknown()).optional(),
		subject: z.string(),
	})
	.superRefine((data, ctx) => {
		const propsSchema = Templates[data.mailType as TemplateType].props;
		if (propsSchema) {
			const result = propsSchema.safeParse(data.mailProps);
			if (!result.success) {
				for (const issue of result.error.issues) {
					ctx.addIssue({
						...issue,
						path: ["mailProps", ...(issue.path ?? [])],
					});
				}
			}
		}
	});
type FormValues = z.infer<typeof Schema>;
export const FormAddCodaEmail = ({ submitMutation }: FormProps) => {
	z.config(z.locales.it());

	const form = useZodForm(Schema, {
		defaultValues: {
			expires_date: new Date(),
			expires_time: "00:00:00",
			mailType: TemplateKeys[0],
			mailProps: undefined,
			subject: "",
		},
	});

	function onSubmit(fields: FormValues) {
		const template = {
			mailType: fields.mailType,
			props: fields.mailProps as MailsTemplates["props"],
		} as MailsTemplates;

		const values: {
			lock_expires: Date;
			template: MailsTemplates;
			subject: string;
		} = {
			lock_expires: new Date(
				`${fields.expires_date.toISOString().split("T")[0]}T${fields.expires_time}`,
			),
			template,
			subject: fields.subject,
		};
		submitMutation(values);
	}

	const type = form.watch("mailType");

	useEffect(() => {
		form.setValue("mailProps", {});
	}, [type, form]);

	useWatch({
		name: "mailProps",
		control: form.control,
		compute: (props) => {
			if (!props) return;
			if ("title" in props) {
				form.setValue("subject", props.title as string);
				return;
			}
		},
	});

	return (
		<>
			<Form {...form}>
				
				<form
					className="space-y-8 px-0.5"
					onSubmit={form.handleSubmit(onSubmit)}
				>
					<div className="grid w-full grid-cols-2 items-center gap-4">
						<FormField
							control={form.control}
							name="expires_date"
							render={({ field }) => (
								<FormItem>
									<div className="flex flex-wrap items-center gap-x-2">
										<FormLabel htmlFor="titolo">Data Invio</FormLabel>
										<FormMessage />
									</div>
									<FormControl>
										<Popover>
											<PopoverTrigger asChild>
												<Button
													className="w-full justify-between bg-card font-normal"
													id="date-picker-optional"
													variant="outline"
												>
													{field.value
														? format(field.value, "PPP", { locale: it })
														: "Seleziona data"}
													<ChevronDownIcon />
												</Button>
											</PopoverTrigger>
											<PopoverContent
												align="start"
												className="w-auto overflow-hidden p-0"
											>
												<Calendar
													captionLayout="dropdown"
													defaultMonth={field.value}
													mode="single"
													onSelect={(date) => {
														field.onChange(date);
													}}
													selected={field.value}
												/>
											</PopoverContent>
										</Popover>
									</FormControl>
								</FormItem>
							)}
						/>
						<FormField
							control={form.control}
							name="expires_time"
							render={({ field }) => (
								<FormItem>
									<div className="flex flex-wrap items-center gap-x-2">
										<FormLabel htmlFor="titolo">Ora Invio</FormLabel>
										<FormMessage />
									</div>
									<FormControl>
										<Input
											className="appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
											defaultValue="10:30:00"
											id="time-picker-optional"
											onChange={(e) => field.onChange(e.target.value)}
											step="1"
											type="time"
										/>
									</FormControl>
								</FormItem>
							)}
						/>
					</div>
					<FormField
						control={form.control}
						name="mailType"
						render={({ field }) => (
							<FormItem className="w-full">
								<div className="flex flex-wrap items-center gap-x-2">
									<FormLabel htmlFor="select-mailType">Modello</FormLabel>
									<FormMessage />
								</div>
								<FormControl>
									<MultiSelect
										defaultValue={
											field.value
												? {
														label: Templates[field.value].title,
														value: field.value,
													}
												: undefined
										}
										elementId="select-mailType"
										elementName="mailType"
										isMulti={false}
										onValueChange={(value) => {
											field.onChange(value.value as TemplateType);
										}}
										options={TemplateKeys.map((key) => ({
											label: Templates[key].title,
											value: key,
										}))}
										placeholder="Seleziona..."
									/>
								</FormControl>
							</FormItem>
						)}
					/>

					<MailPropSection mailType={type as TemplateType} />
					<FormField
						control={form.control}
						name="subject"
						render={({ field }) => (
							<FormItem>
								<div className="flex flex-wrap items-center gap-x-2">
									<FormLabel htmlFor="subject">Oggetto</FormLabel>
									<FormMessage />
								</div>
								<FormControl>
									<Input placeholder="" {...field} id="subject" />
								</FormControl>
							</FormItem>
						)}
					/>

					<Button type="submit">Salva</Button>
				</form>
			</Form>
		</>
	);
};

// --- Zod v4 schema introspection helpers ---

function getType(schema: unknown): string {
	// biome-ignore lint/suspicious/noExplicitAny: Zod v4 internal introspection
	return (schema as any)?.type ?? "unknown";
}

function unwrap(schema: unknown): unknown {
	const t = getType(schema);
	if (t === "optional" || t === "nullable")
		// biome-ignore lint/suspicious/noExplicitAny: Zod v4 internal introspection
		return unwrap((schema as any).def.innerType);
	return schema;
}

function extractShape(schema: unknown): Record<string, unknown> {
	if (!schema || typeof schema !== "object") return {};
	// biome-ignore lint/suspicious/noExplicitAny: Zod v4 internal introspection
	const s = schema as any;
	const t = getType(s);

	if (t === "optional" || t === "nullable")
		return extractShape(s.def.innerType);
	if (s.shape && typeof s.shape === "object") return s.shape;
	if (t === "intersection")
		return { ...extractShape(s.def.left), ...extractShape(s.def.right) };
	if (t === "union" && Array.isArray(s.def.options)) {
		const merged: Record<string, unknown> = {};
		for (const opt of s.def.options) {
			for (const [k, v] of Object.entries(extractShape(opt))) {
				if (!merged[k] || getFieldType(merged[k]) === "skip") merged[k] = v;
			}
		}
		return merged;
	}
	return {};
}

type FieldType = "text" | "checkbox" | "number" | "object" | "skip";

function getFieldType(schema: unknown): FieldType {
	const inner = unwrap(schema);
	const t = getType(inner);
	switch (t) {
		case "boolean":
			return "checkbox";
		case "number":
			return "number";
		case "object":
			return "object";
		case "custom":
		case "undefined":
		case "unknown":
			return "skip";
		default:
			return "text";
	}
}

function isOptionalField(schema: unknown): boolean {
	const t = getType(schema);
	return t === "optional" || t === "nullable";
}

const FieldRenderer = ({
	fieldSchema,
	name,
	label,
}: {
	fieldSchema: unknown;
	name: string;
	label: string;
}) => {
	const { control } = useFormContext();
	const fieldType = getFieldType(fieldSchema);
	const optional = isOptionalField(fieldSchema);

	if (fieldType === "skip") return null;

	if (fieldType === "object") {
		const nestedShape = extractShape(fieldSchema);
		const entries = Object.entries(nestedShape);
		if (entries.length === 0) return null;
		return (
			<fieldset className="space-y-3 rounded-md border p-3">
				<legend className="px-1 font-medium text-sm">
					{label}
					{optional && (
						<span className="ml-1 text-muted-foreground text-xs">
							(opzionale)
						</span>
					)}
				</legend>
				{entries.map(([key, nested]) => (
					<FieldRenderer
						fieldSchema={nested}
						key={key}
						label={key}
						name={`${name}.${key}`}
					/>
				))}
			</fieldset>
		);
	}

	return (
		<FormField
			control={control}
			// biome-ignore lint/suspicious/noExplicitAny: dynamic field name
			name={name as any}
			render={({ field }) => (
				<FormItem>
					<div className="flex flex-wrap items-center gap-x-2">
						<FormLabel>
							{label}
							{optional && (
								<span className="ml-1 text-muted-foreground text-xs">
									(opzionale)
								</span>
							)}
						</FormLabel>
						<FormMessage />
					</div>
					<FormControl>
						{fieldType === "checkbox" ? (
							<input
								checked={!!(field.value as boolean)}
								className="h-4 w-4"
								onChange={(e) => field.onChange(e.target.checked)}
								type="checkbox"
							/>
						) : (
							<Input
								onChange={
									fieldType === "number"
										? (e) => field.onChange(Number(e.target.value))
										: field.onChange
								}
								type={fieldType}
								value={(field.value as string | number) ?? ""}
							/>
						)}
					</FormControl>
				</FormItem>
			)}
		/>
	);
};

const MailPropSection = ({ mailType }: { mailType: TemplateType }) => {
	const template = Templates[mailType];
	if (!template.props) return null;

	const shape = extractShape(template.props);
	const entries = Object.entries(shape);
	if (entries.length === 0) return null;

	return (
		<div className="space-y-4">
			{entries.map(([key, fieldSchema]) => (
				<FieldRenderer
					fieldSchema={fieldSchema}
					key={key}
					label={key}
					name={`mailProps.${key}`}
				/>
			))}
		</div>
	);
};
