import { useMutation } from "@tanstack/react-query";
import { useEffect, useState } from "react";
import { toast } from "sonner";
import { authClient } from "@/lib/auth-client";
import {
	calculateDrinkCard,
	type GuestEntry,
	type GuestErrors,
	inputCls,
	validateBirthdate,
	validateEmail,
	validateGuests,
	validatePhone,
	validatePostcode,
	validateTextField,
} from "@/lib/registration";
import { orpc } from "@/utils/orpc";
import { GiftSelector } from "./GiftSelector";
import { GuestList } from "./GuestList";

interface WatcherErrors {
	firstName?: string;
	lastName?: string;
	email?: string;
	phone?: string;
	birthdate?: string;
	postcode?: string;
}

interface Props {
	onBack: () => void;
	onSuccess: (token: string, email: string, name: string) => void;
}

// ── Main watcher form ──────────────────────────────────────────────────────

export function WatcherForm({ onBack, onSuccess }: Props) {
	const { data: session } = authClient.useSession();
	const sessionEmail = session?.user?.email ?? "";

	const [data, setData] = useState({
		firstName: "",
		lastName: "",
		email: "",
		phone: "",
		birthdateDay: "",
		birthdateMonth: "",
		birthdateYear: "",
		postcode: "",
		extraQuestions: "",
	});
	const [errors, setErrors] = useState<WatcherErrors>({});
	const [touched, setTouched] = useState<Record<string, boolean>>({});
	const [guests, setGuests] = useState<GuestEntry[]>([]);
	const [guestErrors, setGuestErrors] = useState<GuestErrors[]>([]);
	const [giftAmount, setGiftAmount] = useState(0);

	useEffect(() => {
		if (sessionEmail) {
			setData((prev) => ({ ...prev, email: sessionEmail }));
		}
	}, [sessionEmail]);

	const submitMutation = useMutation({
		...orpc.submitRegistration.mutationOptions(),
		onSuccess: (result) => {
			if (result.managementToken) {
				onSuccess(
					result.managementToken,
					data.email.trim(),
					`${data.firstName.trim()} ${data.lastName.trim()}`.trim(),
				);
			}
		},
		onError: (error) => {
			toast.error(`Er is iets misgegaan: ${error.message}`);
		},
	});

	function getBirthdate(): string {
		const { birthdateYear, birthdateMonth, birthdateDay } = data;
		if (!birthdateYear || !birthdateMonth || !birthdateDay) return "";
		return `${birthdateYear}-${birthdateMonth.padStart(2, "0")}-${birthdateDay.padStart(2, "0")}`;
	}

	function validate(): boolean {
		const birthdate = getBirthdate();
		const fieldErrs: WatcherErrors = {
			firstName: validateTextField(data.firstName, true, "Voornaam"),
			lastName: validateTextField(data.lastName, true, "Achternaam"),
			email: validateEmail(data.email),
			phone: validatePhone(data.phone),
			birthdate: validateBirthdate(birthdate),
			postcode: validatePostcode(data.postcode),
		};
		setErrors(fieldErrs);
		setTouched({
			firstName: true,
			lastName: true,
			email: true,
			phone: true,
			birthdate: true,
			postcode: true,
		});
		const { errors: gErrs, valid: gValid } = validateGuests(guests);
		setGuestErrors(gErrs);
		return !Object.values(fieldErrs).some(Boolean) && gValid;
	}

	function handleChange(
		e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
	) {
		const { name, value } = e.target;
		setData((prev) => ({ ...prev, [name]: value }));
		if (touched[name]) {
			const errMap: Record<string, string | undefined> = {
				firstName: validateTextField(value, true, "Voornaam"),
				lastName: validateTextField(value, true, "Achternaam"),
				email: validateEmail(value),
				phone: validatePhone(value),
			};
			setErrors((prev) => ({ ...prev, [name]: errMap[name] }));
		}
	}

	function handleBlur(
		e: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>,
	) {
		const { name, value } = e.target;
		setTouched((prev) => ({ ...prev, [name]: true }));
		const errMap: Record<string, string | undefined> = {
			firstName: validateTextField(value, true, "Voornaam"),
			lastName: validateTextField(value, true, "Achternaam"),
			email: validateEmail(value),
			phone: validatePhone(value),
		};
		setErrors((prev) => ({ ...prev, [name]: errMap[name] }));
	}

	function handleGuestChange(
		index: number,
		field: keyof GuestEntry,
		value: string,
	) {
		setGuests((prev) => {
			const next = [...prev];
			next[index] = { ...next[index], [field]: value } as GuestEntry;
			return next;
		});
	}

	function handleAddGuest() {
		if (guests.length >= 9) return;
		setGuests((prev) => [
			...prev,
			{
				firstName: "",
				lastName: "",
				email: "",
				phone: "",
				birthdate: "",
				postcode: "",
			},
		]);
		setGuestErrors((prev) => [...prev, {}]);
	}

	function handleRemoveGuest(index: number) {
		setGuests((prev) => prev.filter((_, i) => i !== index));
		setGuestErrors((prev) => prev.filter((_, i) => i !== index));
	}

	function handleSubmit(e: React.FormEvent) {
		e.preventDefault();
		if (!validate()) {
			toast.error("Controleer je invoer");
			return;
		}
		submitMutation.mutate({
			firstName: data.firstName.trim(),
			lastName: data.lastName.trim(),
			email: data.email.trim(),
			phone: data.phone.trim() || undefined,
			birthdate: getBirthdate(),
			postcode: data.postcode.trim(),
			registrationType: "watcher",
			guests: guests.map((g) => ({
				firstName: g.firstName.trim(),
				lastName: g.lastName.trim(),
				email: g.email.trim() || undefined,
				phone: g.phone.trim() || undefined,
				birthdate: g.birthdate.trim(),
				postcode: g.postcode.trim(),
			})),
			extraQuestions: data.extraQuestions.trim() || undefined,
			giftAmount,
		});
	}

	const totalPrice = calculateDrinkCard(guests.length);

	return (
		<div>
			{/* Back + type header */}
			<div className="mb-8 flex items-center gap-4">
				<button
					type="button"
					onClick={onBack}
					className="flex items-center gap-2 text-white/60 transition-colors hover:text-white"
				>
					<svg
						className="h-4 w-4"
						fill="none"
						viewBox="0 0 24 24"
						stroke="currentColor"
						strokeWidth={2}
						aria-hidden="true"
					>
						<path
							strokeLinecap="round"
							strokeLinejoin="round"
							d="M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18"
						/>
					</svg>
					Terug
				</button>
				<div className="h-px flex-1 bg-white/10" />
				<div className="flex items-center gap-2">
					<div className="flex h-8 w-8 items-center justify-center rounded-full bg-teal-400/20 text-teal-300">
						<svg
							className="h-4 w-4"
							fill="none"
							viewBox="0 0 24 24"
							stroke="currentColor"
							strokeWidth={1.5}
							aria-hidden="true"
						>
							<path
								strokeLinecap="round"
								strokeLinejoin="round"
								d="M16.5 6v.75m0 3v.75m0 3v.75m0 3V18m-9-5.25h5.25M7.5 15h3M3.375 5.25c-.621 0-1.125.504-1.125 1.125v3.026a2.999 2.999 0 010 5.198v3.026c0 .621.504 1.125 1.125 1.125h17.25c.621 0 1.125-.504 1.125-1.125v-3.026a2.999 2.999 0 010-5.198V6.375c0-.621-.504-1.125-1.125-1.125H3.375z"
							/>
						</svg>
					</div>
					<span className="font-['Intro',sans-serif] text-teal-300">
						Ik wil komen kijken
					</span>
				</div>
			</div>

			{/* Live price callout */}
			<div className="mb-8 flex items-center gap-4 rounded-lg border border-teal-400/30 bg-teal-400/10 p-5">
				<div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-full bg-teal-400/20 font-bold text-teal-300 text-xl">
					€{totalPrice}
				</div>
				<div>
					<p className="font-semibold text-white">Drinkkaart inbegrepen</p>
					<p className="text-sm text-white/70">
						Je betaald bij registratie
						<strong className="text-teal-300"> €5</strong> (+ €5 per
						medebezoeker) dat gaat naar je drinkkaart.
						{guests.length > 0 && (
							<span className="ml-1 font-semibold text-teal-300">
								Totaal: €{totalPrice} voor {1 + guests.length} personen.
							</span>
						)}
					</p>
				</div>
			</div>

			<form onSubmit={handleSubmit} className="flex flex-col gap-6" noValidate>
				{/* Name row */}
				<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
					<div className="flex flex-col gap-2">
						<label htmlFor="w-firstName" className="text-white text-xl">
							Voornaam <span className="text-red-300">*</span>
						</label>
						<input
							type="text"
							id="w-firstName"
							name="firstName"
							value={data.firstName}
							onChange={handleChange}
							onBlur={handleBlur}
							placeholder="Jouw voornaam"
							autoComplete="given-name"
							aria-required="true"
							aria-invalid={touched.firstName && !!errors.firstName}
							className={inputCls(!!touched.firstName && !!errors.firstName)}
						/>
						{touched.firstName && errors.firstName && (
							<span className="text-red-300 text-sm" role="alert">
								{errors.firstName}
							</span>
						)}
					</div>
					<div className="flex flex-col gap-2">
						<label htmlFor="w-lastName" className="text-white text-xl">
							Achternaam <span className="text-red-300">*</span>
						</label>
						<input
							type="text"
							id="w-lastName"
							name="lastName"
							value={data.lastName}
							onChange={handleChange}
							onBlur={handleBlur}
							placeholder="Jouw achternaam"
							autoComplete="family-name"
							aria-required="true"
							aria-invalid={touched.lastName && !!errors.lastName}
							className={inputCls(!!touched.lastName && !!errors.lastName)}
						/>
						{touched.lastName && errors.lastName && (
							<span className="text-red-300 text-sm" role="alert">
								{errors.lastName}
							</span>
						)}
					</div>
				</div>

				{/* Contact row */}
				<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
					<div className="flex flex-col gap-2">
						<label htmlFor="w-email" className="text-white text-xl">
							E-mail <span className="text-red-300">*</span>
						</label>
						<input
							type="email"
							id="w-email"
							name="email"
							value={data.email}
							onChange={sessionEmail ? undefined : handleChange}
							onBlur={sessionEmail ? undefined : handleBlur}
							readOnly={!!sessionEmail}
							placeholder="jouw@email.be"
							autoComplete="email"
							inputMode="email"
							aria-required="true"
							aria-invalid={touched.email && !!errors.email}
							className={`${inputCls(!!touched.email && !!errors.email)}${sessionEmail ? "cursor-not-allowed opacity-75" : ""}`}
						/>
						{touched.email && errors.email && (
							<span className="text-red-300 text-sm" role="alert">
								{errors.email}
							</span>
						)}
					</div>
					<div className="flex flex-col gap-2">
						<label htmlFor="w-phone" className="text-white text-xl">
							Telefoon
						</label>
						<input
							type="tel"
							id="w-phone"
							name="phone"
							value={data.phone}
							onChange={handleChange}
							onBlur={handleBlur}
							placeholder="06-12345678"
							autoComplete="tel"
							inputMode="tel"
							aria-invalid={touched.phone && !!errors.phone}
							className={inputCls(!!touched.phone && !!errors.phone)}
						/>
						{touched.phone && errors.phone && (
							<span className="text-red-300 text-sm" role="alert">
								{errors.phone}
							</span>
						)}
					</div>
				</div>

				{/* Birthdate + Postcode row */}
				<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
					<div className="flex flex-col gap-2">
						<p className="text-white text-xl">
							Geboortedatum <span className="text-red-300">*</span>
						</p>
						<fieldset className="m-0 flex gap-2 border-0 p-0">
							<legend className="sr-only">Geboortedatum</legend>
							<div className="flex flex-1 flex-col gap-1">
								<label htmlFor="w-birthdateDay" className="sr-only">
									Dag
								</label>
								<select
									id="w-birthdateDay"
									value={data.birthdateDay}
									onChange={(e) =>
										setData((prev) => ({
											...prev,
											birthdateDay: e.target.value,
										}))
									}
									aria-label="Dag"
									className={`border-b bg-transparent pb-2 text-lg text-white transition-colors focus:outline-none ${touched.birthdate && errors.birthdate ? "border-red-400" : "border-white/30 focus:border-white"}`}
								>
									<option value="" className="bg-[#214e51]">
										DD
									</option>
									{Array.from({ length: 31 }, (_, i) => i + 1).map((d) => (
										<option key={d} value={String(d)} className="bg-[#214e51]">
											{String(d).padStart(2, "0")}
										</option>
									))}
								</select>
							</div>
							<div className="flex flex-1 flex-col gap-1">
								<label htmlFor="w-birthdateMonth" className="sr-only">
									Maand
								</label>
								<select
									id="w-birthdateMonth"
									value={data.birthdateMonth}
									onChange={(e) =>
										setData((prev) => ({
											...prev,
											birthdateMonth: e.target.value,
										}))
									}
									aria-label="Maand"
									className={`border-b bg-transparent pb-2 text-lg text-white transition-colors focus:outline-none ${touched.birthdate && errors.birthdate ? "border-red-400" : "border-white/30 focus:border-white"}`}
								>
									<option value="" className="bg-[#214e51]">
										MM
									</option>
									{[
										"Jan",
										"Feb",
										"Mrt",
										"Apr",
										"Mei",
										"Jun",
										"Jul",
										"Aug",
										"Sep",
										"Okt",
										"Nov",
										"Dec",
									].map((m, i) => (
										<option
											key={m}
											value={String(i + 1)}
											className="bg-[#214e51]"
										>
											{m}
										</option>
									))}
								</select>
							</div>
							<div className="flex flex-1 flex-col gap-1">
								<label htmlFor="w-birthdateYear" className="sr-only">
									Jaar
								</label>
								<select
									id="w-birthdateYear"
									value={data.birthdateYear}
									onChange={(e) =>
										setData((prev) => ({
											...prev,
											birthdateYear: e.target.value,
										}))
									}
									aria-label="Jaar"
									className={`border-b bg-transparent pb-2 text-lg text-white transition-colors focus:outline-none ${touched.birthdate && errors.birthdate ? "border-red-400" : "border-white/30 focus:border-white"}`}
								>
									<option value="" className="bg-[#214e51]">
										JJJJ
									</option>
									{Array.from(
										{ length: 100 },
										(_, i) => new Date().getFullYear() - i,
									).map((y) => (
										<option key={y} value={String(y)} className="bg-[#214e51]">
											{y}
										</option>
									))}
								</select>
							</div>
						</fieldset>
						{touched.birthdate && errors.birthdate && (
							<span className="text-red-300 text-sm" role="alert">
								{errors.birthdate}
							</span>
						)}
					</div>

					<div className="flex flex-col gap-2">
						<label htmlFor="w-postcode" className="text-white text-xl">
							Postcode <span className="text-red-300">*</span>
						</label>
						<input
							type="text"
							id="w-postcode"
							name="postcode"
							value={data.postcode}
							onChange={handleChange}
							onBlur={handleBlur}
							placeholder="bv. 9000"
							autoComplete="postal-code"
							inputMode="numeric"
							aria-required="true"
							aria-invalid={touched.postcode && !!errors.postcode}
							className={inputCls(!!touched.postcode && !!errors.postcode)}
						/>
						{touched.postcode && errors.postcode && (
							<span className="text-red-300 text-sm" role="alert">
								{errors.postcode}
							</span>
						)}
					</div>
				</div>

				{/* Guests */}
				<GuestList
					guests={guests}
					errors={guestErrors}
					onChange={handleGuestChange}
					onAdd={handleAddGuest}
					onRemove={handleRemoveGuest}
				/>

				{/* Extra questions */}
				<div className="flex flex-col gap-2 border border-white/10 p-6">
					<label htmlFor="w-extraQuestions" className="text-white text-xl">
						Vragen of opmerkingen
					</label>
					<textarea
						id="w-extraQuestions"
						name="extraQuestions"
						value={data.extraQuestions}
						onChange={handleChange}
						onBlur={handleBlur}
						placeholder="Heb je nog vragen of iets dat we moeten weten?"
						rows={3}
						autoComplete="off"
						className="resize-none bg-transparent text-lg text-white transition-all placeholder:text-white/40 focus:outline-none"
					/>
				</div>

				{/* Gift selector */}
				<div className="border border-white/10 p-6">
					<h3 className="mb-4 font-['Intro',sans-serif] text-white text-xl">
						Vrijwillige Gift
					</h3>
					<GiftSelector value={giftAmount} onChange={setGiftAmount} />
				</div>

				<div className="flex flex-col items-center gap-4 pt-4">
					<button
						type="submit"
						disabled={submitMutation.isPending}
						aria-busy={submitMutation.isPending}
						className="bg-white px-12 py-4 font-['Intro',sans-serif] text-[#214e51] text-xl transition-all hover:scale-105 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-white/50 focus:ring-offset-2 focus:ring-offset-[#214e51] disabled:cursor-not-allowed disabled:opacity-50 md:text-2xl"
					>
						{submitMutation.isPending ? (
							<span className="flex items-center gap-2">
								<svg
									className="h-5 w-5 animate-spin"
									xmlns="http://www.w3.org/2000/svg"
									fill="none"
									viewBox="0 0 24 24"
									aria-label="Laden"
								>
									<circle
										className="opacity-25"
										cx="12"
										cy="12"
										r="10"
										stroke="currentColor"
										strokeWidth="4"
									/>
									<path
										className="opacity-75"
										fill="currentColor"
										d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
									/>
								</svg>
								Bezig...
							</span>
						) : (
							"Bevestigen"
						)}
					</button>
					<a
						href="/contact"
						className="text-sm text-white/60 transition-colors hover:text-white"
					>
						Nog vragen? Neem contact op
					</a>
				</div>
			</form>
		</div>
	);
}
