import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { createFileRoute, Link, useParams } from "@tanstack/react-router";
import { useState } from "react";
import { toast } from "sonner";
import { GiftSelector } from "@/components/registration/GiftSelector";
import { GuestList } from "@/components/registration/GuestList";
import {
	calculateDrinkCard,
	type GuestEntry,
	inputCls,
	parseGuests,
} from "@/lib/registration";
import { orpc } from "@/utils/orpc";

export const Route = createFileRoute("/manage/$token")({
	component: ManageRegistrationPage,
});

// ---------------------------------------------------------------------------
// Shared layout wrappers
// ---------------------------------------------------------------------------

function PageShell({ children }: { children: React.ReactNode }) {
	return (
		<div>
			<div className="mx-auto max-w-5xl px-6 py-12">{children}</div>
		</div>
	);
}

function BackLink() {
	return (
		<Link
			to="/account"
			className="link-hover mb-8 inline-block text-white/80 hover:text-white"
		>
			← Terug naar account
		</Link>
	);
}

// ---------------------------------------------------------------------------
// Payment status badges
// ---------------------------------------------------------------------------

function PaidBadge() {
	return (
		<div className="inline-flex items-center gap-2 rounded-full border border-green-400/40 bg-green-400/10 px-4 py-1.5 font-semibold text-green-400 text-sm">
			<svg
				className="h-4 w-4"
				fill="none"
				viewBox="0 0 24 24"
				stroke="currentColor"
				strokeWidth={2}
				aria-label="Betaald"
			>
				<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
			</svg>
			Betaling ontvangen
		</div>
	);
}

function PendingBadge() {
	return (
		<div className="inline-flex items-center gap-2 rounded-full border border-yellow-400/40 bg-yellow-400/10 px-4 py-1.5 font-semibold text-sm text-yellow-400">
			<svg
				className="h-4 w-4"
				fill="none"
				viewBox="0 0 24 24"
				stroke="currentColor"
				strokeWidth={2}
				aria-label="In afwachting"
			>
				<path
					strokeLinecap="round"
					strokeLinejoin="round"
					d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
				/>
			</svg>
			Betaling in afwachting
		</div>
	);
}

function ExtraPaymentBadge({ amountCents }: { amountCents: number }) {
	const euros = amountCents / 100;
	return (
		<div className="inline-flex items-center gap-2 rounded-full border border-orange-400/40 bg-orange-400/10 px-4 py-1.5 font-semibold text-orange-400 text-sm">
			<svg
				className="h-4 w-4"
				fill="none"
				viewBox="0 0 24 24"
				stroke="currentColor"
				strokeWidth={2}
				aria-label="Extra betaling vereist"
			>
				<path
					strokeLinecap="round"
					strokeLinejoin="round"
					d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"
				/>
			</svg>
			Extra betaling vereist — €{euros.toFixed(euros % 1 === 0 ? 0 : 2)}
		</div>
	);
}

// ---------------------------------------------------------------------------
// Edit form (inline on the manage page)
// ---------------------------------------------------------------------------

interface EditFormProps {
	token: string;
	initialData: {
		firstName: string;
		lastName: string;
		email: string;
		phone: string | null;
		birthdate: string;
		postcode: string;
		registrationType: string;
		artForm: string | null;
		experience: string | null;
		isOver16: boolean;
		extraQuestions: string | null;
		guests: string | null;
		paymentStatus: string | null;
		giftAmount: number | null;
	};
	onCancel: () => void;
	onSaved: () => void;
}

function EditForm({ token, initialData, onCancel, onSaved }: EditFormProps) {
	// Narrow the string from DB to the valid union; fall back to "watcher"
	const initialType: "performer" | "watcher" =
		initialData.registrationType === "performer" ? "performer" : "watcher";

	const [formData, setFormData] = useState({
		firstName: initialData.firstName,
		lastName: initialData.lastName,
		email: initialData.email,
		phone: initialData.phone ?? "",
		birthdate: initialData.birthdate ?? "",
		postcode: initialData.postcode ?? "",
		registrationType: initialType,
		artForm: initialData.artForm ?? "",
		experience: initialData.experience ?? "",
		isOver16: initialData.isOver16,
		extraQuestions: initialData.extraQuestions ?? "",
	});
	const [formGuests, setFormGuests] = useState<GuestEntry[]>(
		parseGuests(initialData.guests),
	);
	const [giftAmount, setGiftAmount] = useState(initialData.giftAmount ?? 0);

	const updateMutation = useMutation({
		...orpc.updateRegistration.mutationOptions(),
		onSuccess: () => {
			toast.success("Inschrijving bijgewerkt!");
			onSaved();
		},
		onError: (err) => {
			toast.error(`Opslaan mislukt: ${err.message}`);
		},
	});

	const isWatcher = formData.registrationType === "watcher";
	const totalDrinkCard = isWatcher ? calculateDrinkCard(formGuests.length) : 0;
	const originalGuestCount = parseGuests(initialData.guests).length;
	const isPaid =
		initialData.paymentStatus === "paid" ||
		initialData.paymentStatus === "extra_payment_pending";
	const extraGuests = formGuests.length - originalGuestCount;

	function handleSubmit(e: React.FormEvent) {
		e.preventDefault();
		const performer = formData.registrationType === "performer";
		updateMutation.mutate({
			token,
			firstName: formData.firstName.trim(),
			lastName: formData.lastName.trim(),
			email: formData.email.trim(),
			phone: formData.phone.trim() || undefined,
			registrationType: formData.registrationType,
			artForm: performer ? formData.artForm.trim() || undefined : undefined,
			experience: performer
				? formData.experience.trim() || undefined
				: undefined,
			isOver16: performer ? formData.isOver16 : false,
			birthdate: formData.birthdate.trim(),
			postcode: formData.postcode.trim(),
			guests: performer
				? []
				: formGuests.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: formData.extraQuestions.trim() || undefined,
			giftAmount,
		});
	}

	return (
		<>
			<BackLink />
			<h1 className="mb-8 font-['Intro',sans-serif] text-4xl text-white">
				Bewerk inschrijving
			</h1>

			<form onSubmit={handleSubmit} className="space-y-6">
				{/* Name */}
				<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
					<div>
						<label htmlFor="firstName" className="mb-2 block text-white">
							Voornaam *
						</label>
						<input
							id="firstName"
							type="text"
							required
							value={formData.firstName}
							onChange={(e) =>
								setFormData((p) => ({ ...p, firstName: e.target.value }))
							}
							className={inputCls(false)}
						/>
					</div>
					<div>
						<label htmlFor="lastName" className="mb-2 block text-white">
							Achternaam *
						</label>
						<input
							id="lastName"
							type="text"
							required
							value={formData.lastName}
							onChange={(e) =>
								setFormData((p) => ({ ...p, lastName: e.target.value }))
							}
							className={inputCls(false)}
						/>
					</div>
				</div>

				{/* Contact */}
				<div>
					<label htmlFor="email" className="mb-2 block text-white">
						E-mail *
					</label>
					<input
						id="email"
						type="email"
						required
						value={formData.email}
						onChange={(e) =>
							setFormData((p) => ({ ...p, email: e.target.value }))
						}
						className={inputCls(false)}
					/>
				</div>
				<div>
					<label htmlFor="phone" className="mb-2 block text-white">
						Telefoon
					</label>
					<input
						id="phone"
						type="tel"
						value={formData.phone}
						onChange={(e) =>
							setFormData((p) => ({ ...p, phone: e.target.value }))
						}
						className={inputCls(false)}
					/>
				</div>

				{/* Registration type toggle */}
				<div>
					<p className="mb-3 text-white">Type inschrijving</p>
					<div className="flex gap-4">
						{(["performer", "watcher"] as const).map((type) => (
							<label
								key={type}
								className="flex cursor-pointer items-center gap-3"
							>
								<div className="relative flex shrink-0">
									<input
										type="radio"
										name="registrationType"
										value={type}
										checked={formData.registrationType === type}
										onChange={() =>
											setFormData((p) => ({ ...p, registrationType: type }))
										}
										className="peer sr-only"
									/>
									<div
										className={`h-5 w-5 rounded-full border-2 border-white/50 bg-transparent transition-colors ${type === "performer" ? "peer-checked:border-amber-400 peer-checked:bg-amber-400" : "peer-checked:border-teal-400 peer-checked:bg-teal-400"}`}
									/>
								</div>
								<span className="text-white">
									{type === "performer" ? "Optreden" : "Kijken"}
								</span>
							</label>
						))}
					</div>
				</div>

				{/* Performer fields */}
				{formData.registrationType === "performer" && (
					<div className="space-y-6 border border-amber-400/20 bg-amber-400/5 p-6">
						<div>
							<label htmlFor="artForm" className="mb-2 block text-white">
								Kunstvorm *
							</label>
							<input
								id="artForm"
								type="text"
								required
								value={formData.artForm}
								onChange={(e) =>
									setFormData((p) => ({ ...p, artForm: e.target.value }))
								}
								list="artFormSuggestions"
								className={inputCls(false)}
							/>
							<datalist id="artFormSuggestions">
								<option value="Muziek" />
								<option value="Theater" />
								<option value="Dans" />
								<option value="Beeldende Kunst" />
								<option value="Woordkunst" />
								<option value="Comedy" />
							</datalist>
						</div>
						<div>
							<label htmlFor="experience" className="mb-2 block text-white">
								Ervaring
							</label>
							<input
								id="experience"
								type="text"
								value={formData.experience}
								onChange={(e) =>
									setFormData((p) => ({ ...p, experience: e.target.value }))
								}
								list="experienceSuggestions"
								className={inputCls(false)}
							/>
							<datalist id="experienceSuggestions">
								<option value="Beginner" />
								<option value="Gevorderd" />
								<option value="Professional" />
							</datalist>
						</div>
						<label className="flex cursor-pointer items-center gap-3">
							<div className="relative flex shrink-0">
								<input
									type="checkbox"
									checked={formData.isOver16}
									onChange={(e) =>
										setFormData((p) => ({ ...p, isOver16: e.target.checked }))
									}
									className="peer sr-only"
								/>
								<div className="h-6 w-6 border-2 border-white/50 bg-transparent transition-colors peer-checked:border-amber-400 peer-checked:bg-amber-400" />
								<svg
									className="pointer-events-none absolute top-0 left-0 h-6 w-6 scale-0 text-[#214e51] transition-transform peer-checked:scale-100"
									viewBox="0 0 24 24"
									fill="none"
									stroke="currentColor"
									strokeWidth={3}
									aria-label="Geselecteerd"
								>
									<polyline points="20 6 9 17 4 12" />
								</svg>
							</div>
							<span className="text-white">Ik ben 16 jaar of ouder</span>
						</label>
					</div>
				)}

				{/* Guests for watchers */}
				{isWatcher && (
					<GuestList
						guests={formGuests}
						errors={[]}
						onChange={(idx, field, value) => {
							setFormGuests((prev) => {
								const next = [...prev];
								next[idx] = { ...next[idx], [field]: value } as GuestEntry;
								return next;
							});
						}}
						onAdd={() => {
							if (formGuests.length >= 9) return;
							setFormGuests((prev) => [
								...prev,
								{
									firstName: "",
									lastName: "",
									email: "",
									phone: "",
									birthdate: "",
									postcode: "",
								},
							]);
						}}
						onRemove={(idx) =>
							setFormGuests((prev) => prev.filter((_, i) => i !== idx))
						}
						headerNote={
							<p className="mt-1 text-sm text-white/60">
								Drinkkaart totaal: €{totalDrinkCard} voor{" "}
								{1 + formGuests.length} personen
								{isPaid && extraGuests > 0 && (
									<span className="ml-2 text-yellow-400">
										— Let op: €{extraGuests * 2} extra voor {extraGuests} nieuwe
										gast(en)
									</span>
								)}
							</p>
						}
						isPaid={isPaid}
					/>
				)}

				{/* Extra questions */}
				<div>
					<label htmlFor="extraQuestions" className="mb-2 block text-white">
						Vragen of opmerkingen
					</label>
					<textarea
						id="extraQuestions"
						rows={4}
						value={formData.extraQuestions}
						onChange={(e) =>
							setFormData((p) => ({ ...p, extraQuestions: e.target.value }))
						}
						className="w-full resize-none border border-white/10 bg-transparent p-2 text-lg text-white placeholder:text-white/40 focus:outline-none"
					/>
				</div>

				{/* Gift selector */}
				<div className="border-white/10 border-t pt-6">
					<h3 className="mb-4 font-['Intro',sans-serif] text-white text-xl">
						Vrijwillige Gift
					</h3>
					<GiftSelector
						value={giftAmount}
						onChange={setGiftAmount}
						disabled={isPaid && (initialData.giftAmount ?? 0) > 0}
					/>
				</div>

				<div className="flex flex-wrap items-center gap-4 pt-4">
					<button
						type="submit"
						disabled={updateMutation.isPending}
						className="bg-white px-8 py-3 font-['Intro',sans-serif] text-[#214e51] text-lg transition-all hover:scale-105 hover:bg-gray-100 disabled:opacity-50"
					>
						{updateMutation.isPending ? "Opslaan..." : "Opslaan"}
					</button>
					<button
						type="button"
						onClick={onCancel}
						className="text-white/60 underline underline-offset-2 transition-colors hover:text-white"
					>
						Annuleren
					</button>
				</div>
			</form>
		</>
	);
}

// ---------------------------------------------------------------------------
// Main manage page
// ---------------------------------------------------------------------------

function ManageRegistrationPage() {
	const { token } = useParams({ from: "/manage/$token" });
	const queryClient = useQueryClient();
	const [isEditing, setIsEditing] = useState(false);

	const { data, isLoading, error } = useQuery({
		...orpc.getRegistrationByToken.queryOptions({ input: { token } }),
	});

	const cancelMutation = useMutation({
		...orpc.cancelRegistration.mutationOptions(),
		onSuccess: () => {
			toast.success("Inschrijving geannuleerd");
			queryClient.invalidateQueries({ queryKey: ["getRegistrationByToken"] });
		},
		onError: (err) => {
			toast.error(`Annuleren mislukt: ${err.message}`);
		},
	});

	const checkoutMutation = useMutation({
		...orpc.getCheckoutUrl.mutationOptions(),
		onSuccess: (result) => {
			window.location.href = result.checkoutUrl;
		},
		onError: (err) => {
			toast.error(`Betaling starten mislukt: ${err.message}`);
		},
	});

	function handleCancel() {
		if (
			confirm(
				"Weet je zeker dat je je inschrijving wilt annuleren? Dit kan niet ongedaan worden gemaakt.",
			)
		) {
			cancelMutation.mutate({ token });
		}
	}

	function handleSaved() {
		queryClient.invalidateQueries({ queryKey: ["getRegistrationByToken"] });
		setIsEditing(false);
	}

	// Loading state
	if (isLoading) {
		return (
			<PageShell>
				<div className="animate-pulse text-white/60">Laden...</div>
			</PageShell>
		);
	}

	// Error / not found / cancelled
	if (error || !data || data.cancelledAt) {
		return (
			<PageShell>
				<BackLink />
				<h1 className="mb-4 font-['Intro',sans-serif] text-4xl text-white">
					Inschrijving niet gevonden
				</h1>
				<p className="mb-6 text-white/80">
					Deze link is ongeldig of de inschrijving is geannuleerd.
				</p>
				<a
					href="/#registration"
					className="inline-flex items-center bg-white px-6 py-3 font-['Intro',sans-serif] text-[#214e51] text-lg transition-all hover:scale-105 hover:bg-gray-100"
				>
					Nieuwe inschrijving
				</a>
			</PageShell>
		);
	}

	// Edit mode
	if (isEditing) {
		return (
			<PageShell>
				<EditForm
					token={token}
					initialData={data}
					onCancel={() => setIsEditing(false)}
					onSaved={handleSaved}
				/>
			</PageShell>
		);
	}

	// View mode
	const isPerformer = data.registrationType === "performer";
	const viewGuests = parseGuests(data.guests);

	return (
		<PageShell>
			<BackLink />

			<h1 className="mb-2 font-['Intro',sans-serif] text-4xl text-white">
				Jouw inschrijving
			</h1>
			<p className="mb-8 text-white/60">
				Open Mic Night — vrijdag 24 april 2026
			</p>

			{/* Type badge */}
			<div
				className={`mb-6 inline-flex items-center gap-2 rounded-full border px-4 py-1.5 font-semibold text-sm ${isPerformer ? "border-amber-400/40 bg-amber-400/10 text-amber-300" : "border-teal-400/40 bg-teal-400/10 text-teal-300"}`}
			>
				{isPerformer ? "Artiest" : "Bezoeker"}
				{!isPerformer && (
					<span className="ml-1 opacity-80">
						— Drinkkaart €{data.drinkCardValue ?? 5}
						{viewGuests.length > 0 && ` (${1 + viewGuests.length} personen)`}
					</span>
				)}
			</div>

			{/* Payment status badge:
		    - performers only see a badge if they have a gift to pay, or already paid one
		    - watchers always have a payment (drink card), so always show a badge */}
			{(isPerformer ? (data.giftAmount ?? 0) > 0 : true) && (
				<div className="mb-6">
					{data.paymentStatus === "paid" ? (
						<PaidBadge />
					) : data.paymentStatus === "extra_payment_pending" ? (
						<ExtraPaymentBadge amountCents={data.paymentAmount ?? 0} />
					) : (
						<PendingBadge />
					)}
				</div>
			)}

			{/* Gift display */}
			{(data.giftAmount ?? 0) > 0 && (
				<div className="mb-6">
					<div className="inline-flex items-center gap-2 rounded-full border border-pink-400/40 bg-pink-400/10 px-4 py-1.5 font-semibold text-pink-300 text-sm">
						<span>Vrijwillige gift: €{(data.giftAmount ?? 0) / 100}</span>
					</div>
				</div>
			)}

			{/* Registration details */}
			<div className="space-y-6 rounded-lg border border-white/20 bg-white/5 p-6 md:p-8">
				<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
					<div>
						<p className="text-sm text-white/50">Voornaam</p>
						<p className="text-lg text-white">{data.firstName}</p>
					</div>
					<div>
						<p className="text-sm text-white/50">Achternaam</p>
						<p className="text-lg text-white">{data.lastName}</p>
					</div>
					<div>
						<p className="text-sm text-white/50">E-mail</p>
						<p className="text-lg text-white">{data.email}</p>
					</div>
					<div>
						<p className="text-sm text-white/50">Telefoon</p>
						<p className="text-lg text-white">{data.phone || "—"}</p>
					</div>
				</div>

				{isPerformer && (
					<div className="border-white/10 border-t pt-6">
						<p className="mb-2 text-sm text-white/50">Optreden</p>
						<p className="text-lg text-white">
							{data.artForm || "—"}
							{data.experience && (
								<span className="ml-2 text-white/60">({data.experience})</span>
							)}
						</p>
						<p className="mt-1 text-sm text-white/60">
							{data.isOver16 ? "16+ bevestigd" : "Leeftijd niet bevestigd"}
						</p>
					</div>
				)}

				{!isPerformer && viewGuests.length > 0 && (
					<div className="border-white/10 border-t pt-6">
						<p className="mb-3 text-sm text-white/50">
							Medebezoekers ({viewGuests.length})
						</p>
						<div className="flex flex-col gap-3">
							{viewGuests.map((g, idx) => (
								<div
									key={`view-guest-${
										// biome-ignore lint/suspicious/noArrayIndexKey: stable index
										idx
									}`}
									className="rounded border border-teal-400/20 bg-teal-400/5 p-3"
								>
									<p className="text-white">
										{g.firstName} {g.lastName}
									</p>
									{g.email && (
										<p className="text-sm text-white/60">{g.email}</p>
									)}
									{g.phone && (
										<p className="text-sm text-white/60">{g.phone}</p>
									)}
								</div>
							))}
						</div>
					</div>
				)}

				{data.extraQuestions && (
					<div className="border-white/10 border-t pt-6">
						<p className="mb-2 text-sm text-white/50">Vragen of opmerkingen</p>
						<p className="text-white">{data.extraQuestions}</p>
					</div>
				)}
			</div>

			{/* Actions */}
			<div className="mt-8 flex flex-wrap items-center gap-4">
				{/* Show pay button if there's something to pay (for watchers: drink card, for performers: gift) */}
				{(data.paymentStatus === "pending" ||
					data.paymentStatus === "extra_payment_pending") &&
					(!isPerformer || (data.giftAmount ?? 0) > 0) && (
						<button
							type="button"
							onClick={() => checkoutMutation.mutate({ token })}
							disabled={checkoutMutation.isPending}
							className={`px-8 py-3 font-['Intro',sans-serif] text-lg transition-all hover:scale-105 disabled:opacity-50 ${data.paymentStatus === "extra_payment_pending" ? "bg-orange-400 text-white hover:bg-orange-300" : isPerformer ? "bg-pink-400 text-white hover:bg-pink-300" : "bg-teal-400 text-[#214e51] hover:bg-teal-300"}`}
						>
							{checkoutMutation.isPending
								? "Laden..."
								: data.paymentStatus === "extra_payment_pending"
									? `Extra betalen (€${((data.paymentAmount ?? 0) / 100).toFixed(0)})`
									: isPerformer
										? `Gift betalen (€${((data.giftAmount ?? 0) / 100).toFixed(0)})`
										: "Nu betalen"}
						</button>
					)}
				<button
					type="button"
					onClick={() => setIsEditing(true)}
					className="bg-white px-8 py-3 font-['Intro',sans-serif] text-[#214e51] text-lg transition-all hover:scale-105 hover:bg-gray-100"
				>
					Bewerken
				</button>
				<button
					type="button"
					onClick={handleCancel}
					disabled={cancelMutation.isPending}
					className="border border-red-400/50 px-8 py-3 text-lg text-red-400 transition-all hover:bg-red-400/10 disabled:opacity-50"
				>
					{cancelMutation.isPending ? "Annuleren..." : "Inschrijving annuleren"}
				</button>
			</div>

			<p className="mt-8 text-sm text-white/40">
				Deze link is uniek voor jouw inschrijving. Bewaar deze pagina of de
				bevestigingsmail om je gegevens later aan te passen.
			</p>
		</PageShell>
	);
}
