<script lang="ts">
	import { SvelteDate, SvelteURLSearchParams } from 'svelte/reactivity';
	import { toast } from 'svelte-sonner';
	import { apiFetch } from '$lib/utils/api';
	import * as Modal from '$lib/components/ui/dialog';
	import { Button } from '$lib/components/ui/button';
	import PatchTestModal from './PatchTestModal.svelte';
	import { formatUserName } from '$lib/utils/nameDisplay';
	import { parseWallClockDate } from '$lib/utils/timeSlots';
	import { range } from '$lib/utils/format';

	interface Props {
		open: boolean;
		userId: string;
		openBookingModal: (bookingId: string) => void;
	}

	let { open = $bindable(), userId, openBookingModal }: Props = $props();

	type SocialLogin = {
		provider: string;
		createdAt: string;
	};

	type AdminUserDetail = {
		id: string;
		email?: string;
		firstName: string;
		lastName: string;
		fullName: string;
		phone?: string;
		dateOfBirth?: string;
		profilePicUrl?: string;
		accountRole: string;
		accountType: string;
		loyaltyStamps: number;
		referralCode: string;
		referralCodeUses: number;
		lastLoginAt?: string;
		createdAt: string;
		updatedAt: string;
		notes?: string;
		privacyPolicyConsent: boolean;
		policyConsentUpdatedAt?: string;
		dataRetentionConsent: boolean;
		dataConsentUpdatedAt?: string;
		socialLogins?: SocialLogin[];
		previousFirstName?: string;
		previousLastName?: string;
	};

	type Booking = {
		id: string;
		start_time: string;
		status:
			| 'pending'
			| 'confirmed'
			| 'in_progress'
			| 'completed'
			| 'client_cancelled'
			| 'we_cancelled'
			| 'no_show'
			| 'pending_release'
			| 'deposit_lapsed';
		deposit_required: boolean;
		deposit_paid: boolean;
		services: Array<{
			service_name?: string;
		}>;
		total_amount: number;
	};

	type TopService = {
		name: string;
		count: number;
	};

	type CustomerRelationship = {
		totalSpend: number;
		totalSaved: number;
		totalTips: number;
		totalVisits: number;
		customerFor: string;
		firstVisitDate?: string;
		lastVisitDate?: string;
		topServices: TopService[];
	};

	let selectedUser = $state<AdminUserDetail | null>(null);
	let bookingUserHistory = $state<Booking[]>([]);
	let totalBookings = $state(0);
	let cursors = $state<string[]>(['']);
	let nextCursor = $state<string | null>(null);
	let currentBookingPage = $state(1);
	let totalBookingPages = $state(1);
	let loadingBookings = $state(false);

	let showPatchTestModal = $state(false);
	let hasEligiblePatchTests = $state(false);
	let customerRelationship = $state<CustomerRelationship | null>(null);
	let loadingRelationship = $state(false);
	let giftCardBalance = $state<number | null>(null);

	async function fetchUserDetails() {
		if (!userId) return;

		try {
			const response = await apiFetch(`/api/admin/users/${userId}`, {
				headers: {
					'Content-Type': 'application/json'
				}
			});

			if (response.ok) {
				selectedUser = await response.json();
			} else {
				const text = await response.text();
				toast.error('Failed to load user details: ' + text);
			}
		} catch (err) {
			console.error('Error fetching user details:', err);
			toast.error('Network error loading user details');
		}
	}

	async function fetchEligiblePatchTests() {
		if (!userId) return;
		try {
			const response = await apiFetch(`/api/admin/users/${userId}/patch-tests/eligible`, {
				headers: {
					'Content-Type': 'application/json'
				}
			});
			if (response.ok) {
				const services = await response.json();
				hasEligiblePatchTests = services.length > 0;
			}
		} catch (err) {
			console.error('Error fetching eligible patch tests:', err);
		}
	}

	$effect(() => {
		if (userId) {
			fetchUserDetails();
			fetchEligiblePatchTests();
		}
	});

	async function fetchUserBookings(pageIdx: number = 0) {
		if (!userId) return;

		loadingBookings = true;
		try {
			const params = new SvelteURLSearchParams({
				per_page: '4'
			});
			const cursor = cursors[pageIdx];
			if (cursor) {
				params.set('cursor', cursor);
			}

			const response = await apiFetch(`/api/admin/bookings/user/${userId}?${params}`, {
				headers: {
					'Content-Type': 'application/json'
				}
			});

			if (response.ok) {
				const data = await response.json();

				if (!data.bookings || data.bookings.length === 0) {
					bookingUserHistory = [];
					totalBookings = 0;
					totalBookingPages = 1;
					currentBookingPage = 1;
					cursors = [''];
					nextCursor = null;
					loadingBookings = false;
					return;
				}

				bookingUserHistory = data.bookings || [];
				totalBookings = data.total || 0;
				totalBookingPages = data.totalPages || 1;
				currentBookingPage = pageIdx + 1;
				nextCursor = data.next_cursor ?? null;

				if (nextCursor && cursors.length <= pageIdx + 1) {
					cursors = [...cursors, nextCursor];
				}
			} else {
				const text = await response.text();
				toast.error('Failed to load user bookings: ' + text);
			}
		} catch (err) {
			console.error('Error fetching user bookings:', err);
			toast.error('Network error loading user bookings');
		} finally {
			loadingBookings = false;
		}
	}

	function nextBookingPage() {
		if (!nextCursor || currentBookingPage >= totalBookingPages) return;
		fetchUserBookings(currentBookingPage);
	}

	function previousBookingPage() {
		if (currentBookingPage <= 1) return;
		fetchUserBookings(currentBookingPage - 2);
	}

	async function fetchCustomerRelationship() {
		if (!userId) return;

		loadingRelationship = true;
		try {
			const response = await apiFetch(`/api/admin/users/${userId}/relationship`, {
				headers: {
					'Content-Type': 'application/json'
				}
			});

			if (response.ok) {
				customerRelationship = await response.json();
			} else {
				customerRelationship = null;
			}
		} catch (err) {
			console.error('Error fetching customer relationship:', err);
			customerRelationship = null;
		} finally {
			loadingRelationship = false;
		}
	}

	async function fetchGiftCardBalance() {
		if (!userId) return;
		try {
			const res = await apiFetch(`/api/admin/users/${userId}/giftcard-balance`);
			if (res.ok) {
				const data = await res.json();
				giftCardBalance = data.balance;
			}
		} catch {
			/* ignore */
		}
	}

	$effect(() => {
		if (open && userId) {
			fetchUserDetails();
			fetchUserBookings();
			fetchCustomerRelationship();
			fetchGiftCardBalance();
		}
	});

	function handleOpenBooking(bookingId: string) {
		openBookingModal(bookingId);
	}
</script>

<Modal.Root bind:open>
	<Modal.Content
		class="max-h-[90vh] max-w-[calc(100%-2rem)] overflow-y-auto sm:max-w-md md:max-w-3xl"
	>
		<Modal.Header>
			<div class="flex items-center justify-between">
				<div>
					<Modal.Title class="text-lg font-semibold">User Details</Modal.Title>
					{#if selectedUser}
						<div class="mt-1 text-sm text-gray-500">ID: {selectedUser.id}</div>
					{/if}
				</div>
				{#if selectedUser}
					<span
						class="inline-flex items-center rounded-full px-3 py-1 text-sm font-medium
						{selectedUser.accountRole === 'admin'
							? 'bg-purple-100 text-purple-800'
							: selectedUser.accountRole === 'verified_email'
								? 'bg-emerald-100 text-emerald-800'
								: selectedUser.accountRole === 'unverified_email'
									? 'bg-yellow-100 text-yellow-800'
									: 'bg-gray-100 text-gray-800'}"
					>
						{selectedUser.accountRole}
					</span>
				{/if}
			</div>
		</Modal.Header>

		{#if selectedUser}
			<div class="space-y-6 px-4 pb-4">
				<!-- Personal Information -->
				<div class="rounded-lg border border-gray-200 bg-gray-50 p-4">
					<h3 class="mb-3 text-sm font-semibold tracking-wide text-gray-600 uppercase">
						Personal Information
					</h3>
					<div class="grid gap-3 md:grid-cols-2">
						<div>
							<div class="text-xs text-gray-500">Full Name</div>
							<div class="font-medium">
								{formatUserName(
									selectedUser.fullName,
									selectedUser.previousFirstName,
									selectedUser.previousLastName
								)}
							</div>
						</div>
						<div>
							<div class="text-xs text-gray-500">Email</div>
							<div class="font-medium break-words" title={selectedUser.email}>
								{selectedUser.email || '—'}
							</div>
						</div>
						<div>
							<div class="text-xs text-gray-500">Phone</div>
							<div class="font-medium">{selectedUser.phone || '—'}</div>
						</div>
						<div>
							<div class="text-xs text-gray-500">Date of Birth</div>
							<div class="font-medium">
								{#if selectedUser.dateOfBirth}
									{(() => {
										const dob = new SvelteDate(selectedUser.dateOfBirth);
										const dateStr = dob.toLocaleDateString('en-US', {
											year: 'numeric',
											month: 'long',
											day: 'numeric'
										});
										const today = new SvelteDate();
										let age = today.getFullYear() - dob.getFullYear();
										const m = today.getMonth() - dob.getMonth();
										if (m < 0 || (m === 0 && today.getDate() < dob.getDate())) age--;
										return `${dateStr} (${age})`;
									})()}
								{:else}
									—
								{/if}
							</div>
						</div>
						<div>
							<div class="text-xs text-gray-500">First Visit</div>
							<div class="font-medium">
								{#if customerRelationship?.firstVisitDate}
									{new SvelteDate(customerRelationship.firstVisitDate).toLocaleDateString('en-US', {
										year: 'numeric',
										month: 'short',
										day: 'numeric'
									})}
								{:else}
									—
								{/if}
							</div>
						</div>
						<div>
							<div class="text-xs text-gray-500">Last Visit</div>
							<div class="font-medium">
								{#if customerRelationship?.lastVisitDate}
									{new SvelteDate(customerRelationship.lastVisitDate).toLocaleDateString('en-US', {
										weekday: 'short',
										day: 'numeric',
										month: 'short',
										year: 'numeric'
									})}
								{:else}
									—
								{/if}
							</div>
						</div>
					</div>
					{#if selectedUser.profilePicUrl}
						<div class="mt-3">
							<div class="text-xs text-gray-500">Profile Picture</div>
							<img
								src={selectedUser.profilePicUrl}
								alt="Profile"
								class="mt-2 h-20 w-20 rounded-lg object-cover md:h-24 md:w-24"
							/>
						</div>
					{/if}
					{#if selectedUser.notes}
						<div class="mt-3 rounded-md border border-amber-200 bg-amber-50 p-3">
							<div class="mb-1 text-xs font-semibold text-amber-800">Staff Notes</div>
							<div class="text-sm text-amber-900">{selectedUser.notes}</div>
						</div>
					{/if}
				</div>

				<!-- Booking History -->
				<div class="rounded-lg border border-gray-200 bg-gray-50 p-4">
					<h3 class="mb-3 text-sm font-semibold tracking-wide text-gray-600 uppercase">
						Booking History ({totalBookings})
					</h3>
					{#if bookingUserHistory.length === 0 && !loadingBookings}
						<div class="text-center text-sm text-gray-500">No bookings found</div>
					{:else if bookingUserHistory.length > 0}
						<div class="space-y-2 {loadingBookings ? 'opacity-60' : ''}">
							{#each bookingUserHistory as booking (booking.id)}
								<div class="rounded-md border border-gray-300 bg-white p-3">
									<div class="flex items-start justify-between">
										<div class="flex-1">
											<div class="font-medium">
												{(() => {
													const date = parseWallClockDate(booking.start_time);
													const dateStr = date.toLocaleDateString('en-US', {
														weekday: 'long',
														day: 'numeric',
														month: 'short'
													});
													const timeStr = date.toLocaleTimeString('en-US', {
														hour: 'numeric',
														minute: '2-digit',
														hour12: true
													});
													return `${dateStr} at ${timeStr}`;
												})()}
											</div>
											<div class="mt-1 flex flex-wrap items-center gap-2 text-xs">
												<span
													class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium
												{booking.status === 'confirmed' || booking.status === 'in_progress'
														? 'bg-emerald-100 text-emerald-800'
														: booking.status === 'pending'
															? 'bg-yellow-100 text-yellow-800'
															: booking.status === 'completed'
																? 'bg-green-100 text-green-800'
																: booking.status === 'client_cancelled' ||
																	  booking.status === 'we_cancelled' ||
																	  booking.status === 'deposit_lapsed'
																	? 'bg-red-100 text-red-800'
																	: 'bg-gray-100 text-gray-800'}"
												>
													{booking.status.replace('_', ' ')}
												</span>

												{#if booking.deposit_required}
													{#if booking.status === 'pending'}
														<span
															class="inline-flex items-center rounded-full bg-blue-100 px-2 py-0.5 text-xs font-medium text-blue-800"
														>
															Will Require Deposit
														</span>
													{:else if (booking.status === 'confirmed' || booking.status === 'in_progress') && !booking.deposit_paid}
														<span
															class="inline-flex items-center rounded-full bg-orange-100 px-2 py-0.5 text-xs font-medium text-orange-800"
														>
															Deposit Due
														</span>
													{:else if booking.deposit_paid}
														<span
															class="inline-flex items-center rounded-full bg-green-100 px-2 py-0.5 text-xs font-medium text-green-800"
														>
															Deposit Paid
														</span>
													{/if}
												{/if}

												<span class="text-gray-500">
													{booking.services.map((s) => s.service_name).join(', ')}
												</span>
											</div>
											<div class="mt-1 text-sm font-semibold text-gray-900">
												£{booking.total_amount.toFixed(2)}
											</div>
										</div>
										<Button
											variant="outline"
											size="sm"
											onclick={() => handleOpenBooking(booking.id)}>View</Button
										>
									</div>
								</div>
							{/each}
						</div>

						{#if totalBookingPages > 1}
							<div class="mt-3 flex items-center justify-between border-t pt-3 text-sm">
								<Button
									variant="outline"
									size="sm"
									onclick={previousBookingPage}
									disabled={currentBookingPage === 1 || loadingBookings}
								>
									Previous
								</Button>
								<span class="text-xs text-gray-600">
									Page {currentBookingPage} of {totalBookingPages}
								</span>
								<Button
									variant="outline"
									size="sm"
									onclick={nextBookingPage}
									disabled={currentBookingPage === totalBookingPages || loadingBookings}
								>
									Next
								</Button>
							</div>
						{/if}
					{/if}
				</div>

				{#if loadingRelationship}
					<div class="rounded-lg border border-gray-200 bg-gray-50 p-4">
						<h3 class="mb-3 text-sm font-semibold tracking-wide text-gray-600 uppercase">
							Customer Relationship
						</h3>
						<div class="space-y-2">
							{#each range(5) as i (i)}
								<div class="h-10 animate-pulse rounded-md bg-gray-200"></div>
							{/each}
						</div>
					</div>
				{:else if customerRelationship}
					<div class="rounded-lg border border-gray-200 bg-gray-50 p-4">
						<h3 class="mb-3 text-sm font-semibold tracking-wide text-gray-600 uppercase">
							Customer Relationship
						</h3>
						<div class="grid gap-3 md:grid-cols-5">
							<div>
								<div class="text-xs text-gray-500">Total Spend</div>
								<div class="text-2xl font-bold text-emerald-600">
									£{customerRelationship.totalSpend.toFixed(2)}
								</div>
							</div>
							<div>
								<div class="text-xs text-gray-500">Total Saved</div>
								<div class="text-2xl font-bold text-fuchsia-600">
									£{customerRelationship.totalSaved.toFixed(2)}
								</div>
							</div>
							<div>
								<div class="text-xs text-gray-500">Total Tips</div>
								<div class="text-2xl font-bold text-amber-600">
									£{customerRelationship.totalTips.toFixed(2)}
								</div>
							</div>
							<div>
								<div class="text-xs text-gray-500">Total Visits</div>
								<div class="text-2xl font-bold text-blue-600">
									{customerRelationship.totalVisits}
								</div>
							</div>
							<div>
								<div class="text-xs text-gray-500">Customer For</div>
								<div class="text-2xl font-bold text-purple-600">
									{customerRelationship.customerFor || '—'}
								</div>
							</div>
						</div>

						{#if giftCardBalance !== null && giftCardBalance > 0}
							<div class="mt-3 border-t pt-3">
								<div class="text-xs text-gray-500">Gift Card Balance</div>
								<div class="text-2xl font-bold text-green-600">
									£{giftCardBalance.toFixed(2)}
								</div>
							</div>
						{/if}

						{#if customerRelationship.topServices && customerRelationship.topServices.length > 0}
							<div class="mt-4">
								<div class="mb-2 text-xs font-semibold text-gray-600">Most Booked Services</div>
								<div class="flex flex-wrap gap-2">
									{#each customerRelationship.topServices as service (service.name)}
										<span
											class="inline-flex items-center rounded-full bg-blue-100 px-3 py-1 text-sm font-medium text-blue-800"
										>
											{service.name}
											<span class="ml-1 text-xs text-blue-600">({service.count})</span>
										</span>
									{/each}
								</div>
							</div>
						{/if}
					</div>
				{/if}

				<!-- Loyalty & Referrals -->
				<div class="rounded-lg border border-gray-200 bg-gray-50 p-4">
					<h3 class="mb-3 text-sm font-semibold tracking-wide text-gray-600 uppercase">
						Loyalty & Referrals
					</h3>
					<div class="grid gap-3 md:grid-cols-3">
						<div>
							<div class="text-xs text-gray-500">Loyalty Stamps</div>
							<div class="text-2xl font-bold text-emerald-600">{selectedUser.loyaltyStamps}</div>
						</div>
						<div>
							<div class="text-xs text-gray-500">Referral Code</div>
							<div class="font-mono text-sm font-medium">{selectedUser.referralCode}</div>
						</div>
						<div>
							<div class="text-xs text-gray-500">Referrals Made</div>
							<div class="text-2xl font-bold text-purple-600">{selectedUser.referralCodeUses}</div>
						</div>
					</div>
				</div>

				{#if hasEligiblePatchTests}
					<!-- Patch Test Actions -->
					<div class="rounded-lg border border-gray-200 bg-gray-50 p-4">
						<h3 class="mb-3 text-sm font-semibold tracking-wide text-gray-600 uppercase">
							Patch Tests
						</h3>
						<p class="mb-3 text-sm text-gray-600">
							Record patch test completion to allow this user to book services requiring one.
						</p>
						<Button variant="outline" onclick={() => (showPatchTestModal = true)}>
							<svg
								xmlns="http://www.w3.org/2000/svg"
								class="mr-2 h-4 w-4"
								viewBox="0 0 24 24"
								fill="none"
								stroke="currentColor"
								stroke-width="2"
							>
								<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
							</svg>
							Record Patch Test
						</Button>
					</div>
				{/if}
			</div>
		{/if}

		<Modal.Footer class="flex items-center justify-end gap-2">
			<Button onclick={() => (open = false)}>Close</Button>
		</Modal.Footer>
	</Modal.Content>
</Modal.Root>

{#if selectedUser}
	<PatchTestModal
		bind:open={showPatchTestModal}
		userId={selectedUser.id}
		userName={formatUserName(
			selectedUser.fullName,
			selectedUser.previousFirstName,
			selectedUser.previousLastName
		)}
		onPatchTestAdded={() => {
			fetchUserDetails();
		}}
	/>
{/if}
