import { useMutation, useQuery } from "@tanstack/react-query";
import { createFileRoute, Link, useNavigate } from "@tanstack/react-router";
import {
	Check,
	ChevronDown,
	ChevronRight,
	ChevronsUpDown,
	ChevronUp,
	Clipboard,
	ClipboardCheck,
	Download,
	LogOut,
	Search,
	Users,
	X,
} from "lucide-react";
import { useMemo, useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import {
	Card,
	CardContent,
	CardDescription,
	CardHeader,
	CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { authClient } from "@/lib/auth-client";
import { orpc } from "@/utils/orpc";

export const Route = createFileRoute("/admin/")({
	component: AdminPage,
});

type Guest = {
	firstName: string;
	lastName: string;
	email?: string;
	phone?: string;
};

function parseGuests(raw: unknown): Guest[] {
	if (!raw) return [];
	try {
		const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
		return Array.isArray(parsed) ? parsed : [];
	} catch {
		return [];
	}
}

function AdminPage() {
	const navigate = useNavigate();
	const [search, setSearch] = useState("");
	const [registrationType, setRegistrationType] = useState<
		"performer" | "watcher" | ""
	>("");
	const [artForm, setArtForm] = useState("");
	const [fromDate, setFromDate] = useState("");
	const [toDate, setToDate] = useState("");
	const [page, setPage] = useState(1);
	const pageSize = 20;

	const [copiedId, setCopiedId] = useState<string | null>(null);
	const [expandedGuests, setExpandedGuests] = useState<Set<string>>(new Set());

	// Get current session to check user role
	const sessionQuery = useQuery({
		queryKey: ["session"],
		queryFn: () => authClient.getSession(),
	});

	const handleCopyManageUrl = (token: string, id: string) => {
		const url = `${window.location.origin}/manage/${token}`;
		navigator.clipboard.writeText(url).then(() => {
			setCopiedId(id);
			toast.success("Beheerlink gekopieerd");
			setTimeout(() => setCopiedId(null), 2000);
		});
	};

	const toggleGuestExpand = (id: string) => {
		setExpandedGuests((prev) => {
			const next = new Set(prev);
			if (next.has(id)) next.delete(id);
			else next.add(id);
			return next;
		});
	};

	type SortKey =
		| "naam"
		| "email"
		| "type"
		| "details"
		| "gasten"
		| "gift"
		| "betaling"
		| "datum";
	type SortDir = "asc" | "desc";
	const [sortKey, setSortKey] = useState<SortKey>("datum");
	const [sortDir, setSortDir] = useState<SortDir>("desc");

	const handleSort = (key: SortKey) => {
		if (sortKey === key) {
			setSortDir((d) => (d === "asc" ? "desc" : "asc"));
		} else {
			setSortKey(key);
			setSortDir("asc");
		}
	};

	const statsQuery = useQuery(orpc.getRegistrationStats.queryOptions());

	const registrationsQuery = useQuery(
		orpc.getRegistrations.queryOptions({
			input: {
				search: search || undefined,
				registrationType: registrationType || undefined,
				artForm: artForm || undefined,
				fromDate: fromDate || undefined,
				toDate: toDate || undefined,
				page,
				pageSize,
			},
		}),
	);

	const adminRequestsQuery = useQuery(orpc.getAdminRequests.queryOptions());

	const exportMutation = useMutation({
		...orpc.exportRegistrations.mutationOptions(),
		onSuccess: (data: { csv: string; filename: string }) => {
			const blob = new Blob([data.csv], { type: "text/csv" });
			const url = window.URL.createObjectURL(blob);
			const a = document.createElement("a");
			a.href = url;
			a.download = data.filename;
			document.body.appendChild(a);
			a.click();
			document.body.removeChild(a);
			window.URL.revokeObjectURL(url);
		},
	});

	const approveRequestMutation = useMutation({
		...orpc.approveAdminRequest.mutationOptions(),
		onSuccess: () => {
			toast.success("Admin toegang goedgekeurd");
			adminRequestsQuery.refetch();
		},
		onError: (error) => {
			toast.error(`Fout: ${error.message}`);
		},
	});

	const rejectRequestMutation = useMutation({
		...orpc.rejectAdminRequest.mutationOptions(),
		onSuccess: () => {
			toast.success("Admin toegang geweigerd");
			adminRequestsQuery.refetch();
		},
		onError: (error) => {
			toast.error(`Fout: ${error.message}`);
		},
	});

	const requestAdminMutation = useMutation({
		...orpc.requestAdminAccess.mutationOptions(),
		onSuccess: () => {
			toast.success("Admin toegang aangevraagd!");
		},
		onError: (error) => {
			toast.error(`Aanvraag mislukt: ${error.message}`);
		},
	});

	const handleSignOut = async () => {
		await authClient.signOut();
		navigate({ to: "/" });
	};

	const handleExport = () => {
		exportMutation.mutate(undefined);
	};

	const handleApprove = (requestId: string) => {
		approveRequestMutation.mutate({ requestId });
	};

	const handleReject = (requestId: string) => {
		rejectRequestMutation.mutate({ requestId });
	};

	const handleRequestAdmin = () => {
		requestAdminMutation.mutate(undefined);
	};

	const stats = statsQuery.data;
	const registrations = registrationsQuery.data?.data ?? [];
	const pagination = registrationsQuery.data?.pagination;
	const adminRequests = adminRequestsQuery.data ?? [];
	const pendingRequests = adminRequests.filter((r) => r.status === "pending");

	const performerCount =
		stats?.byType.find((t) => t.registrationType === "performer")?.count ?? 0;
	const watcherCount =
		stats?.byType.find((t) => t.registrationType === "watcher")?.count ?? 0;

	// Use server-side totalGuestCount from stats (accurate across all pages)
	const totalGuestCount =
		(stats as { totalGuestCount?: number } | undefined)?.totalGuestCount ?? 0;
	const totalWatcherAttendees = watcherCount + totalGuestCount;

	const totalDrinkCardValue = registrations
		.filter((r) => r.registrationType === "watcher")
		.reduce((sum, r) => sum + (r.drinkCardValue ?? 0), 0);
	const totalGiftRevenue = (stats?.totalGiftRevenue as number | undefined) ?? 0;

	const sortedRegistrations = useMemo(() => {
		const sorted = [...registrations].sort((a, b) => {
			let valA: string | number = 0;
			let valB: string | number = 0;
			switch (sortKey) {
				case "naam":
					valA = `${a.firstName} ${a.lastName}`.toLowerCase();
					valB = `${b.firstName} ${b.lastName}`.toLowerCase();
					break;
				case "email":
					valA = a.email.toLowerCase();
					valB = b.email.toLowerCase();
					break;
				case "type":
					valA = a.registrationType ?? "";
					valB = b.registrationType ?? "";
					break;
				case "details":
					valA =
						(a.registrationType === "performer"
							? a.artForm
							: `€${a.drinkCardValue ?? 5}`) ?? "";
					valB =
						(b.registrationType === "performer"
							? b.artForm
							: `€${b.drinkCardValue ?? 5}`) ?? "";
					break;
				case "gasten": {
					valA = parseGuests(a.guests).length;
					valB = parseGuests(b.guests).length;
					break;
				}
				case "gift":
					valA = a.giftAmount ?? 0;
					valB = b.giftAmount ?? 0;
					break;
				case "betaling":
					valA = a.paymentStatus ?? "pending";
					valB = b.paymentStatus ?? "pending";
					break;
				case "datum":
					valA = new Date(a.createdAt).getTime();
					valB = new Date(b.createdAt).getTime();
					break;
			}
			if (valA < valB) return sortDir === "asc" ? -1 : 1;
			if (valA > valB) return sortDir === "asc" ? 1 : -1;
			return 0;
		});
		return sorted;
	}, [registrations, sortKey, sortDir]);

	const SortIcon = ({ col }: { col: SortKey }) => {
		if (sortKey !== col)
			return <ChevronsUpDown className="ml-1 inline h-3.5 w-3.5 opacity-40" />;
		return sortDir === "asc" ? (
			<ChevronUp className="ml-1 inline h-3.5 w-3.5" />
		) : (
			<ChevronDown className="ml-1 inline h-3.5 w-3.5" />
		);
	};

	const thClass =
		"px-4 py-3 text-left font-medium text-xs text-white/60 uppercase tracking-wider cursor-pointer select-none hover:text-white/90 whitespace-nowrap";

	const formatCents = (cents: number | null | undefined) => {
		if (!cents || cents <= 0) return "-";
		const euros = cents / 100;
		return `€${euros.toFixed(euros % 1 === 0 ? 0 : 2)}`;
	};

	// Check if user is admin
	const user = sessionQuery.data?.data?.user as
		| { role?: string; name?: string }
		| undefined;
	const isAdmin = user?.role === "admin";
	const isAuthenticated = !!sessionQuery.data?.data?.user;

	// Show loading state while checking session
	if (sessionQuery.isLoading) {
		return (
			<div className="flex min-h-[calc(100dvh-2.75rem)] items-center justify-center px-4 py-8 sm:min-h-[calc(100dvh-3.5rem)]">
				<p className="text-white/60">Laden...</p>
			</div>
		);
	}

	// Show login prompt for non-authenticated users
	if (!isAuthenticated) {
		return (
			<div className="flex min-h-[calc(100dvh-2.75rem)] items-center justify-center overflow-y-auto px-4 py-8 sm:min-h-[calc(100dvh-3.5rem)]">
				<Card className="my-auto w-full max-w-md border-white/10 bg-white/5">
					<CardHeader className="text-center">
						<CardTitle className="font-['Intro',sans-serif] text-3xl text-white">
							Inloggen Vereist
						</CardTitle>
						<CardDescription className="text-white/60">
							Je moet ingelogd zijn om admin toegang aan te vragen
						</CardDescription>
					</CardHeader>
					<CardContent>
						<div className="space-y-4">
							<Button
								onClick={() => navigate({ to: "/login" })}
								className="w-full bg-white text-[#214e51] hover:bg-white/90"
							>
								Inloggen
							</Button>

							<Link
								to="/"
								className="block text-center text-sm text-white/40 hover:text-white"
							>
								← Terug naar website
							</Link>
						</div>
					</CardContent>
				</Card>
			</div>
		);
	}

	// Show request admin UI for non-admin users
	if (!isAdmin) {
		return (
			<div className="flex min-h-[calc(100dvh-2.75rem)] items-center justify-center overflow-y-auto px-4 py-8 sm:min-h-[calc(100dvh-3.5rem)]">
				<Card className="my-auto w-full max-w-md border-white/10 bg-white/5">
					<CardHeader className="text-center">
						<CardTitle className="font-['Intro',sans-serif] text-3xl text-white">
							Admin Toegang Vereist
						</CardTitle>
						<CardDescription className="text-white/60">
							Je hebt geen admin rechten voor dit dashboard
						</CardDescription>
					</CardHeader>
					<CardContent>
						<div className="space-y-4">
							<div className="rounded-lg border border-white/10 bg-white/5 p-4">
								<p className="mb-3 text-center text-sm text-white/60">
									Admin-toegang aanvragen?
								</p>
								<Button
									onClick={handleRequestAdmin}
									disabled={requestAdminMutation.isPending}
									className="w-full bg-white text-[#214e51] hover:bg-white/90"
								>
									{requestAdminMutation.isPending
										? "Bezig..."
										: "Vraag Admin Toegang Aan"}
								</Button>
							</div>

							<Button
								onClick={() => navigate({ to: "/account" })}
								variant="outline"
								className="w-full border-white/20 bg-transparent text-white hover:bg-white/10"
							>
								Ga naar mijn account
							</Button>

							<Button
								onClick={handleSignOut}
								variant="outline"
								className="w-full border-white/20 bg-transparent text-white/60 hover:bg-white/10 hover:text-white"
							>
								<LogOut className="mr-2 h-4 w-4" />
								Uitloggen
							</Button>

							<Link
								to="/"
								className="block text-center text-sm text-white/40 hover:text-white"
							>
								← Terug naar website
							</Link>
						</div>
					</CardContent>
				</Card>
			</div>
		);
	}

	return (
		<div>
			{/* Header */}
			<header className="border-white/10 border-b bg-[#214e51]/95 px-4 py-4 sm:px-8 sm:py-6">
				<div className="mx-auto flex max-w-7xl flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
					<div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-4">
						<Link
							to="/"
							className="text-sm text-white hover:opacity-80 sm:text-base"
						>
							← Terug naar website
						</Link>
						<h1 className="font-['Intro',sans-serif] text-2xl text-white sm:text-3xl">
							Admin Dashboard
						</h1>
					</div>
					<div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-3">
						<Link
							to="/admin/drinkkaart"
							className="inline-flex items-center justify-center rounded-lg border border-white/30 px-4 py-2 text-sm text-white/80 transition-colors hover:bg-white/10 hover:text-white"
						>
							Drinkkaart beheer
						</Link>
						<Button
							onClick={handleSignOut}
							variant="outline"
							className="border-white/30 bg-transparent text-white hover:bg-white/10"
						>
							<LogOut className="mr-2 h-4 w-4" />
							Uitloggen
						</Button>
					</div>
				</div>
			</header>

			{/* Main Content */}
			<main className="mx-auto max-w-7xl px-4 py-4 sm:px-6 sm:py-6 lg:px-8 lg:py-8">
				{/* Pending Admin Requests */}
				{pendingRequests.length > 0 && (
					<Card className="mb-4 border-yellow-500/30 bg-yellow-500/10 sm:mb-6">
						<CardHeader className="px-4 py-4 sm:px-6">
							<CardTitle className="font-['Intro',sans-serif] text-lg text-yellow-200 sm:text-xl">
								Openstaande Admin Aanvragen ({pendingRequests.length})
							</CardTitle>
							<CardDescription className="text-sm text-yellow-200/60">
								Gebruikers die admin toegang hebben aangevraagd
							</CardDescription>
						</CardHeader>
						<CardContent className="px-4 pb-4 sm:px-6 sm:pb-6">
							<div className="space-y-3">
								{pendingRequests.map((request) => (
									<div
										key={request.id}
										className="flex flex-col gap-3 rounded-lg border border-yellow-500/20 bg-yellow-500/5 p-3 sm:flex-row sm:items-center sm:justify-between sm:p-4"
									>
										<div className="min-w-0">
											<p className="truncate font-medium text-white">
												{request.userName}
											</p>
											<p className="truncate text-sm text-white/60">
												{request.userEmail}
											</p>
											<p className="text-white/40 text-xs">
												Aangevraagd:{" "}
												{new Date(request.requestedAt).toLocaleDateString(
													"nl-BE",
												)}
											</p>
										</div>
										<div className="flex flex-col gap-2 sm:flex-row">
											<Button
												onClick={() => handleApprove(request.id)}
												disabled={approveRequestMutation.isPending}
												size="sm"
												className="bg-green-600 text-white hover:bg-green-700"
											>
												<Check className="mr-1 h-4 w-4" />
												Goedkeuren
											</Button>
											<Button
												onClick={() => handleReject(request.id)}
												disabled={rejectRequestMutation.isPending}
												size="sm"
												variant="outline"
												className="border-red-500/30 text-red-400 hover:bg-red-500/10"
											>
												<X className="mr-1 h-4 w-4" />
												Weigeren
											</Button>
										</div>
									</div>
								))}
							</div>
						</CardContent>
					</Card>
				)}

				{/* Stats Cards */}
				<div className="mb-8 grid grid-cols-2 gap-3 sm:grid-cols-3 sm:gap-4 lg:grid-cols-5 lg:gap-6">
					{/* Total registrations */}
					<Card className="border-white/10 bg-white/5">
						<CardHeader className="pb-2">
							<CardDescription className="text-white/60 text-xs sm:text-sm">
								Totaal inschrijvingen
							</CardDescription>
							<CardTitle className="font-['Intro',sans-serif] text-2xl text-white sm:text-3xl lg:text-4xl">
								{stats?.total ?? 0}
							</CardTitle>
						</CardHeader>
						<CardContent>
							<Users className="h-5 w-5 text-white/40" />
						</CardContent>
					</Card>

					{/* Today */}
					<Card className="border-white/10 bg-white/5">
						<CardHeader className="pb-2">
							<CardDescription className="text-white/60 text-xs sm:text-sm">
								Vandaag ingeschreven
							</CardDescription>
							<CardTitle className="font-['Intro',sans-serif] text-2xl text-white sm:text-3xl lg:text-4xl">
								{stats?.today ?? 0}
							</CardTitle>
						</CardHeader>
						<CardContent>
							<span className="text-white/40 text-xs sm:text-sm">
								Nieuwe registraties vandaag
							</span>
						</CardContent>
					</Card>

					{/* Performers */}
					<Card className="border-amber-400/20 bg-amber-400/5">
						<CardHeader className="pb-2">
							<CardDescription className="text-amber-300/70 text-xs sm:text-sm">
								Artiesten
							</CardDescription>
							<CardTitle className="font-['Intro',sans-serif] text-2xl text-amber-300 sm:text-3xl lg:text-4xl">
								{performerCount}
							</CardTitle>
						</CardHeader>
						<CardContent>
							<div className="space-y-1">
								{stats?.byArtForm.slice(0, 2).map((item) => (
									<div
										key={item.artForm}
										className="flex items-center justify-between text-xs"
									>
										<span className="truncate text-amber-300/70">
											{item.artForm || "Onbekend"}
										</span>
										<span className="text-amber-300">{item.count}</span>
									</div>
								))}
							</div>
						</CardContent>
					</Card>

					{/* Watchers + guests (real attendees count) */}
					<Card className="border-teal-400/20 bg-teal-400/5">
						<CardHeader className="pb-2">
							<CardDescription className="text-teal-300/70 text-xs sm:text-sm">
								Bezoekers
							</CardDescription>
							<CardTitle className="font-['Intro',sans-serif] text-2xl text-teal-300 sm:text-3xl lg:text-4xl">
								{totalWatcherAttendees}
							</CardTitle>
						</CardHeader>
						<CardContent>
							<div className="space-y-1 text-xs">
								<div className="flex items-center justify-between">
									<span className="text-teal-300/70">Inschrijvingen</span>
									<span className="text-teal-300">{watcherCount}</span>
								</div>
								{totalGuestCount > 0 && (
									<div className="flex items-center justify-between">
										<span className="text-teal-300/70">Gasten</span>
										<span className="text-teal-300">+{totalGuestCount}</span>
									</div>
								)}
								<div className="hidden sm:flex sm:items-center sm:justify-between">
									<span className="text-teal-300/70">Drinkkaart</span>
									<span className="text-teal-300">€{totalDrinkCardValue}</span>
								</div>
							</div>
						</CardContent>
					</Card>

					{/* Gifts */}
					<Card className="border-pink-400/20 bg-pink-400/5">
						<CardHeader className="pb-2">
							<CardDescription className="text-pink-300/70 text-xs sm:text-sm">
								Vrijwillige Gifts
							</CardDescription>
							<CardTitle className="font-['Intro',sans-serif] text-2xl text-pink-300 sm:text-3xl lg:text-4xl">
								€{Math.round(totalGiftRevenue / 100)}
							</CardTitle>
						</CardHeader>
						<CardContent>
							<span className="text-white/40 text-xs sm:text-sm">
								Totale gift opbrengst
							</span>
						</CardContent>
					</Card>
				</div>

				{/* Filters */}
				<Card className="mb-6 border-white/10 bg-white/5">
					<CardHeader className="px-4 py-4 sm:px-6 sm:py-6">
						<CardTitle className="font-['Intro',sans-serif] text-lg text-white sm:text-xl">
							Filters
						</CardTitle>
					</CardHeader>
					<CardContent className="px-4 pb-4 sm:px-6 sm:pb-6">
						<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 sm:gap-4 lg:grid-cols-5">
							<div>
								<label
									htmlFor="search"
									className="mb-1.5 block text-white/60 text-xs sm:mb-2 sm:text-sm"
								>
									Zoeken
								</label>
								<div className="relative">
									<Search className="absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-white/40" />
									<Input
										id="search"
										placeholder="Naam of email..."
										value={search}
										onChange={(e) => setSearch(e.target.value)}
										className="border-white/20 bg-white/10 pl-10 text-sm text-white placeholder:text-white/40 sm:text-base"
									/>
								</div>
							</div>

							<div>
								<label
									htmlFor="typeFilter"
									className="mb-1.5 block text-white/60 text-xs sm:mb-2 sm:text-sm"
								>
									Type
								</label>
								<select
									id="typeFilter"
									value={registrationType}
									onChange={(e) =>
										setRegistrationType(
											e.target.value as "performer" | "watcher" | "",
										)
									}
									className="w-full rounded-md border border-white/20 bg-white/10 px-3 py-2 text-sm text-white focus:outline-none focus:ring-2 focus:ring-white/20 sm:text-base"
								>
									<option value="" className="bg-[#214e51]">
										Alle types
									</option>
									<option value="performer" className="bg-[#214e51]">
										Artiesten
									</option>
									<option value="watcher" className="bg-[#214e51]">
										Bezoekers
									</option>
								</select>
							</div>

							<div>
								<label
									htmlFor="artForm"
									className="mb-1.5 block text-white/60 text-xs sm:mb-2 sm:text-sm"
								>
									Kunstvorm
								</label>
								<Input
									id="artForm"
									placeholder="Filter op kunstvorm..."
									value={artForm}
									onChange={(e) => setArtForm(e.target.value)}
									className="border-white/20 bg-white/10 text-sm text-white placeholder:text-white/40 sm:text-base"
								/>
							</div>

							<div>
								<label
									htmlFor="fromDate"
									className="mb-1.5 block text-white/60 text-xs sm:mb-2 sm:text-sm"
								>
									Vanaf
								</label>
								<Input
									id="fromDate"
									type="date"
									value={fromDate}
									onChange={(e) => setFromDate(e.target.value)}
									className="border-white/20 bg-white/10 text-sm text-white [color-scheme:dark] sm:text-base"
								/>
							</div>

							<div>
								<label
									htmlFor="toDate"
									className="mb-1.5 block text-white/60 text-xs sm:mb-2 sm:text-sm"
								>
									Tot
								</label>
								<Input
									id="toDate"
									type="date"
									value={toDate}
									onChange={(e) => setToDate(e.target.value)}
									className="border-white/20 bg-white/10 text-sm text-white [color-scheme:dark] sm:text-base"
								/>
							</div>
						</div>
					</CardContent>
				</Card>

				{/* Export Button */}
				<div className="mb-4 flex flex-col gap-2 sm:mb-6 sm:flex-row sm:items-center sm:justify-between">
					<p className="text-sm text-white/60">
						{pagination?.total ?? 0} registraties gevonden
						{totalGuestCount > 0 && (
							<span className="ml-2 text-teal-300/70">
								(+{totalGuestCount} gasten ={" "}
								{(pagination?.total ?? 0) + totalGuestCount} aanwezigen totaal)
							</span>
						)}
					</p>
					<Button
						onClick={handleExport}
						disabled={exportMutation.isPending}
						className="w-full bg-white text-[#214e51] hover:bg-white/90 sm:w-auto"
					>
						<Download className="mr-2 h-4 w-4" />
						{exportMutation.isPending ? "Exporteren..." : "Exporteer CSV"}
					</Button>
				</div>

				{/* Registrations Table / Cards */}
				<Card className="border-white/10 bg-white/5">
					<CardContent className="p-0">
						{/* Desktop Table */}
						<div className="hidden overflow-x-auto lg:block">
							<table className="w-full">
								<thead>
									<tr className="border-white/10 border-b">
										<th className={thClass} onClick={() => handleSort("naam")}>
											Naam <SortIcon col="naam" />
										</th>
										<th className={thClass} onClick={() => handleSort("email")}>
											Email <SortIcon col="email" />
										</th>
										<th className="whitespace-nowrap px-4 py-3 text-left font-medium text-white/60 text-xs uppercase tracking-wider">
											Telefoon
										</th>
										<th className={thClass} onClick={() => handleSort("type")}>
											Type <SortIcon col="type" />
										</th>
										<th
											className={thClass}
											onClick={() => handleSort("details")}
										>
											Details <SortIcon col="details" />
										</th>
										<th
											className={thClass}
											onClick={() => handleSort("gasten")}
										>
											Gasten <SortIcon col="gasten" />
										</th>
										<th className={thClass} onClick={() => handleSort("gift")}>
											Gift <SortIcon col="gift" />
										</th>
										<th
											className={thClass}
											onClick={() => handleSort("betaling")}
										>
											Betaling <SortIcon col="betaling" />
										</th>
										<th className={thClass} onClick={() => handleSort("datum")}>
											Datum <SortIcon col="datum" />
										</th>
										<th className="whitespace-nowrap px-4 py-3 text-left font-medium text-white/60 text-xs uppercase tracking-wider">
											Link
										</th>
									</tr>
								</thead>
								<tbody>
									{registrationsQuery.isLoading ? (
										<tr>
											<td
												colSpan={10}
												className="px-4 py-8 text-center text-white/60"
											>
												Laden...
											</td>
										</tr>
									) : sortedRegistrations.length === 0 ? (
										<tr>
											<td
												colSpan={10}
												className="px-4 py-8 text-center text-white/60"
											>
												Geen registraties gevonden
											</td>
										</tr>
									) : (
										sortedRegistrations.map((reg) => {
											const isPerformer = reg.registrationType === "performer";
											const guests = parseGuests(reg.guests);
											const guestCount = guests.length;
											const isExpanded = expandedGuests.has(reg.id);

											const detailLabel = isPerformer
												? reg.artForm || "-"
												: `€${reg.drinkCardValue ?? 5} drinkkaart`;

											const dateLabel = (() => {
												try {
													return new Date(reg.createdAt).toLocaleDateString(
														"nl-BE",
														{
															day: "2-digit",
															month: "2-digit",
															year: "numeric",
														},
													);
												} catch {
													return "-";
												}
											})();

											return (
												<>
													<tr
														key={reg.id}
														className="border-white/5 border-b hover:bg-white/5"
													>
														<td className="px-4 py-3 font-medium text-white">
															{reg.firstName} {reg.lastName}
														</td>
														<td className="px-4 py-3 text-sm text-white/70">
															{reg.email}
														</td>
														<td className="px-4 py-3 text-sm text-white/60">
															{reg.phone || "-"}
														</td>
														<td className="px-4 py-3">
															<span
																className={`inline-flex items-center rounded-full px-2 py-0.5 font-semibold text-xs ${isPerformer ? "bg-amber-400/15 text-amber-300" : "bg-teal-400/15 text-teal-300"}`}
															>
																{isPerformer ? "Artiest" : "Bezoeker"}
															</span>
														</td>
														<td className="px-4 py-3 text-sm text-white/70">
															{detailLabel}
														</td>
														<td className="px-4 py-3 text-sm text-white/70">
															{guestCount > 0 ? (
																<button
																	type="button"
																	onClick={() => toggleGuestExpand(reg.id)}
																	className="inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-teal-300 transition-colors hover:bg-teal-400/10"
																>
																	{isExpanded ? (
																		<ChevronDown className="h-3.5 w-3.5" />
																	) : (
																		<ChevronRight className="h-3.5 w-3.5" />
																	)}
																	{guestCount} gast
																	{guestCount === 1 ? "" : "en"}
																</button>
															) : (
																"-"
															)}
														</td>
														<td className="px-4 py-3 text-pink-300/70 text-sm">
															{formatCents(reg.giftAmount)}
														</td>
														<td className="px-4 py-3">
															{isPerformer ? (
																<span className="text-sm text-white/30">-</span>
															) : reg.paymentStatus === "paid" ? (
																<span className="inline-flex items-center gap-1 font-medium text-green-400 text-sm">
																	<Check className="h-3.5 w-3.5" />
																	Betaald
																</span>
															) : reg.paymentStatus ===
																"extra_payment_pending" ? (
																<span className="inline-flex items-center gap-1 font-medium text-orange-400 text-sm">
																	<span className="h-1.5 w-1.5 rounded-full bg-orange-400" />
																	Extra (€
																	{((reg.paymentAmount ?? 0) / 100).toFixed(0)})
																</span>
															) : (
																<span className="text-sm text-yellow-400">
																	Open
																</span>
															)}
														</td>
														<td className="px-4 py-3 text-sm text-white/50 tabular-nums">
															{dateLabel}
														</td>
														<td className="px-4 py-3">
															{reg.managementToken ? (
																<button
																	type="button"
																	title="Kopieer beheerlink"
																	onClick={() =>
																		handleCopyManageUrl(
																			reg.managementToken as string,
																			reg.id,
																		)
																	}
																	className="inline-flex items-center justify-center rounded p-1 text-white/40 transition-colors hover:bg-white/10 hover:text-white"
																>
																	{copiedId === reg.id ? (
																		<ClipboardCheck className="h-4 w-4 text-green-400" />
																	) : (
																		<Clipboard className="h-4 w-4" />
																	)}
																</button>
															) : (
																<span className="text-sm text-white/20">—</span>
															)}
														</td>
													</tr>
													{/* Expandable guest details row */}
													{isExpanded && guestCount > 0 && (
														<tr
															key={`${reg.id}-guests`}
															className="border-white/5 border-b bg-teal-900/20"
														>
															<td colSpan={10} className="px-6 py-3">
																<div className="space-y-1.5">
																	<p className="mb-2 font-medium text-teal-300/70 text-xs uppercase tracking-wider">
																		Gasten van {reg.firstName} {reg.lastName}
																	</p>
																	{guests.map((g, i) => (
																		<div
																			// biome-ignore lint/suspicious/noArrayIndexKey: guest order is stable within a registration
																			key={i}
																			className="flex flex-wrap items-center gap-x-4 gap-y-0.5 rounded bg-teal-400/5 px-3 py-1.5 text-sm"
																		>
																			<span className="w-5 shrink-0 text-white/40 text-xs">
																				{i + 1}.
																			</span>
																			<span className="font-medium text-white">
																				{g.firstName} {g.lastName}
																			</span>
																			{g.email && (
																				<span className="text-white/60">
																					{g.email}
																				</span>
																			)}
																			{g.phone && (
																				<span className="text-white/50">
																					{g.phone}
																				</span>
																			)}
																			{!g.email && !g.phone && (
																				<span className="text-white/30 text-xs italic">
																					geen contactgegevens
																				</span>
																			)}
																		</div>
																	))}
																</div>
															</td>
														</tr>
													)}
												</>
											);
										})
									)}
								</tbody>
							</table>
						</div>

						{/* Mobile Cards */}
						<div className="lg:hidden">
							{registrationsQuery.isLoading ? (
								<div className="px-4 py-8 text-center text-white/60">
									Laden...
								</div>
							) : sortedRegistrations.length === 0 ? (
								<div className="px-4 py-8 text-center text-white/60">
									Geen registraties gevonden
								</div>
							) : (
								<div className="divide-y divide-white/5">
									{sortedRegistrations.map((reg) => {
										const isPerformer = reg.registrationType === "performer";
										const guests = parseGuests(reg.guests);
										const guestCount = guests.length;
										const isExpanded = expandedGuests.has(reg.id);

										const detailLabel = isPerformer
											? reg.artForm || "-"
											: `€${reg.drinkCardValue ?? 5} drinkkaart`;

										const dateLabel = (() => {
											try {
												return new Date(reg.createdAt).toLocaleDateString(
													"nl-BE",
													{
														day: "2-digit",
														month: "2-digit",
														year: "2-digit",
													},
												);
											} catch {
												return "-";
											}
										})();

										return (
											<div key={reg.id}>
												<div className="p-4 hover:bg-white/5">
													<div className="flex items-start justify-between gap-3">
														<div className="min-w-0 flex-1">
															<div className="flex items-center gap-2">
																<span className="truncate font-medium text-white">
																	{reg.firstName} {reg.lastName}
																</span>
															</div>
															<div className="mt-1 flex items-center gap-2 text-white/60 text-xs">
																<span className="truncate">{reg.email}</span>
																{reg.phone && (
																	<span className="shrink-0">
																		• {reg.phone}
																	</span>
																)}
															</div>
														</div>
														<div className="flex items-center gap-2">
															<span
																className={`shrink-0 rounded-full px-2 py-0.5 font-semibold text-xs ${isPerformer ? "bg-amber-400/15 text-amber-300" : "bg-teal-400/15 text-teal-300"}`}
															>
																{isPerformer ? "Artiest" : "Bezoeker"}
															</span>
															{reg.managementToken && (
																<button
																	type="button"
																	title="Kopieer beheerlink"
																	onClick={() =>
																		handleCopyManageUrl(
																			reg.managementToken as string,
																			reg.id,
																		)
																	}
																	className="shrink-0 rounded p-1.5 text-white/40 transition-colors hover:bg-white/10 hover:text-white"
																>
																	{copiedId === reg.id ? (
																		<ClipboardCheck className="h-4 w-4 text-green-400" />
																	) : (
																		<Clipboard className="h-4 w-4" />
																	)}
																</button>
															)}
														</div>
													</div>

													<div className="mt-3 flex flex-wrap items-center gap-x-4 gap-y-2 text-xs">
														<div className="text-white/70">
															<span className="text-white/40">Details:</span>{" "}
															{detailLabel}
														</div>
														{guestCount > 0 && (
															<button
																type="button"
																onClick={() => toggleGuestExpand(reg.id)}
																className="inline-flex items-center gap-1 text-teal-300"
															>
																{isExpanded ? (
																	<ChevronDown className="h-3 w-3" />
																) : (
																	<ChevronRight className="h-3 w-3" />
																)}
																{guestCount} gast{guestCount === 1 ? "" : "en"}
															</button>
														)}
														{(reg.giftAmount ?? 0) > 0 && (
															<div className="text-pink-300">
																<span className="text-white/40">Gift:</span>{" "}
																{formatCents(reg.giftAmount)}
															</div>
														)}
														{!isPerformer && (
															<div>
																<span className="text-white/40">Betaling:</span>{" "}
																{reg.paymentStatus === "paid" ? (
																	<span className="inline-flex items-center gap-1 font-medium text-green-400">
																		<Check className="h-3 w-3" />
																		Betaald
																	</span>
																) : reg.paymentStatus ===
																	"extra_payment_pending" ? (
																	<span className="inline-flex items-center gap-1 font-medium text-orange-400">
																		<span className="h-1 w-1 rounded-full bg-orange-400" />
																		Extra (€
																		{((reg.paymentAmount ?? 0) / 100).toFixed(
																			0,
																		)}
																		)
																	</span>
																) : (
																	<span className="text-yellow-400">Open</span>
																)}
															</div>
														)}
														<div className="text-white/50">{dateLabel}</div>
													</div>
												</div>

												{/* Expandable guest details — mobile */}
												{isExpanded && guestCount > 0 && (
													<div className="border-teal-400/10 border-t bg-teal-900/20 px-4 pt-3 pb-4">
														<p className="mb-2 font-medium text-teal-300/70 text-xs uppercase tracking-wider">
															Gasten
														</p>
														<div className="space-y-2">
															{guests.map((g, i) => (
																<div
																	// biome-ignore lint/suspicious/noArrayIndexKey: guest order is stable within a registration
																	key={i}
																	className="rounded bg-teal-400/5 px-3 py-2 text-sm"
																>
																	<span className="mr-2 text-white/40 text-xs">
																		{i + 1}.
																	</span>
																	<span className="font-medium text-white">
																		{g.firstName} {g.lastName}
																	</span>
																	{g.email && (
																		<div className="mt-0.5 text-white/60 text-xs">
																			{g.email}
																		</div>
																	)}
																	{g.phone && (
																		<div className="text-white/50 text-xs">
																			{g.phone}
																		</div>
																	)}
																</div>
															))}
														</div>
													</div>
												)}
											</div>
										);
									})}
								</div>
							)}
						</div>
					</CardContent>
				</Card>

				{/* Pagination */}
				{pagination && pagination.totalPages > 1 && (
					<div className="mt-4 flex items-center justify-center gap-2 sm:mt-6">
						<Button
							onClick={() => setPage((p) => Math.max(1, p - 1))}
							disabled={page === 1}
							variant="outline"
							size="sm"
							className="border-white/20 bg-transparent px-2 text-sm text-white hover:bg-white/10 disabled:opacity-50 sm:px-4"
						>
							<span className="hidden sm:inline">Vorige</span>
							<span className="sm:hidden">←</span>
						</Button>
						<span className="mx-2 text-sm text-white sm:mx-4">
							<span className="sm:hidden">
								{page}/{pagination.totalPages}
							</span>
							<span className="hidden sm:inline">
								Pagina {page} van {pagination.totalPages}
							</span>
						</span>
						<Button
							onClick={() =>
								setPage((p) => Math.min(pagination.totalPages, p + 1))
							}
							disabled={page === pagination.totalPages}
							variant="outline"
							size="sm"
							className="border-white/20 bg-transparent px-2 text-sm text-white hover:bg-white/10 disabled:opacity-50 sm:px-4"
						>
							<span className="hidden sm:inline">Volgende</span>
							<span className="sm:hidden">→</span>
						</Button>
					</div>
				)}
			</main>
		</div>
	);
}
