<script lang="ts">
	import { apiFetch } from '$lib/utils/api';
	import { SvelteDate, SvelteURLSearchParams } from 'svelte/reactivity';
	import { toast } from 'svelte-sonner';

	// shadcn-svelte components
	import { Button } from '$lib/components/ui/button';
	import * as Card from '$lib/components/ui/card';
	import { Input } from '$lib/components/ui/input';
	import type { Booking } from '$lib/types/booking';
	import { formatUserName } from '$lib/utils/nameDisplay';

	// Props
	const { openBookingModal }: { openBookingModal: (bookingId: string) => void } = $props();

	// State
	let bookings = $state<Booking[]>([]);
	let totalBookings = $state(0);
	let bookingQuery = $state('');
	let loadingSearch = $state(false);
	// Cursor-based pagination: cursors[i] = cursor to use when loading page i+1
	// cursors[0] is always '' (empty cursor = first page)
	let cursors = $state<string[]>(['']);
	let currentPage = $state(1);
	let totalPages = $state(1);
	let nextCursor = $state<string | null>(null);
	let initialLoad = $state(true);

	// Fetch bookings from API
	async function fetchBookings(pageIdx: number = 0, search: string = '') {
		loadingSearch = true;
		try {
			const params = new SvelteURLSearchParams({
				per_page: '3'
			});
			const cursor = cursors[pageIdx];
			if (cursor) {
				params.set('cursor', cursor);
			}

			let url = '/api/admin/bookings';
			if (search.trim()) {
				params.set('q', search.trim());
				url = '/api/admin/bookings/search';
			}

			const response = await apiFetch(`${url}?${params}`, {
				method: 'GET',
				headers: {
					'Content-Type': 'application/json'
				}
			});
			if (response.ok) {
				const data = await response.json();

				if (!data.bookings || data.bookings.length === 0) {
					bookings = [];
					totalBookings = 0;
					totalPages = 1;
					currentPage = 1;
					cursors = [''];
					nextCursor = null;
					loadingSearch = false;
					initialLoad = false;
					return;
				}

				bookings = (data.bookings as Booking[]) || [];
				totalBookings = data.total || 0;
				totalPages = data.totalPages ?? 1;
				currentPage = pageIdx + 1;
				nextCursor = data.next_cursor ?? null;

				// Pre-store cursor for the next page so we can go forward
				if (nextCursor && cursors.length <= pageIdx + 1) {
					cursors = [...cursors, nextCursor];
				}
			} else {
				const text = await response.text();
				toast.error('Failed to load bookings: ' + text);
			}
		} catch (err) {
			console.error('Error fetching bookings:', err);
			toast.error('Network error loading bookings');
		} finally {
			loadingSearch = false;
			initialLoad = false;
		}
	}

	function searchBookings() {
		cursors = [''];
		nextCursor = null;
		currentPage = 1;
		fetchBookings(0, bookingQuery);
	}

	function nextPage() {
		if (!nextCursor || currentPage >= totalPages) return;
		// currentPage is 1-indexed; next page index = currentPage
		fetchBookings(currentPage, bookingQuery);
	}

	function previousPage() {
		if (currentPage <= 1) return;
		// currentPage is 1-indexed; previous page index = currentPage - 2
		fetchBookings(currentPage - 2, bookingQuery);
	}

	// Load initial bookings on mount (guarded to run once)
	$effect(() => {
		if (initialLoad) {
			fetchBookings(0);
		}
	});

	// Format booking date/time
	function formatBookingDateTime(startTime: string): string {
		const date = new SvelteDate(startTime);
		const now = new SvelteDate();
		const today = new SvelteDate(now.getFullYear(), now.getMonth(), now.getDate());
		const bookingDate = new SvelteDate(date.getFullYear(), date.getMonth(), date.getDate());
		const daysDiff = Math.floor((bookingDate.getTime() - today.getTime()) / (1000 * 60 * 60 * 24));

		const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
		const months = [
			'Jan',
			'Feb',
			'Mar',
			'Apr',
			'May',
			'June',
			'July',
			'Aug',
			'Sept',
			'Oct',
			'Nov',
			'Dec'
		];

		const day = days[date.getDay()];
		const dateNum = date.getDate();
		const month = months[date.getMonth()];
		const year = date.getFullYear();
		const currentYear = now.getFullYear();
		const hours = date.getHours();
		const minutes = date.getMinutes().toString().padStart(2, '0');
		const ampm = hours >= 12 ? 'pm' : 'am';
		const hour12 = hours % 12 || 12;
		const time = `${hour12}:${minutes}${ampm}`;

		if (daysDiff === 0) return `Today, ${time}`;
		if (daysDiff === 1) return `Tomorrow, ${time}`;
		if (daysDiff > 1 && daysDiff <= 6) return `${day}, ${time}`;
		if (daysDiff < 0 && daysDiff >= -6) return `Last ${day}, ${time}`;

		const suffix =
			dateNum === 1 || dateNum === 21 || dateNum === 31
				? 'st'
				: dateNum === 2 || dateNum === 22
					? 'nd'
					: dateNum === 3 || dateNum === 23
						? 'rd'
						: 'th';
		const yearStr = year !== currentYear ? ` ${year}` : '';
		return `${day}, ${dateNum}${suffix} ${month}${yearStr} at ${time}`;
	}

	// Format services list
	function formatServices(services: Booking['services']): string {
		const serviceNames = services?.map((s) => s.service_name || 'Unknown Service') || [];
		if (serviceNames.length === 0) return 'No services';
		if (serviceNames.length === 1) return serviceNames[0];
		if (serviceNames.length === 2) return serviceNames.join(' and ');
		return `${serviceNames[0]} and ${serviceNames.length - 1} other${serviceNames.length - 1 > 1 ? 's' : ''}`;
	}

	// Get status badge classes
	function getStatusClasses(status: Booking['status']): string {
		const baseClasses = 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium';
		const statusMap: Record<string, string> = {
			confirmed: 'bg-emerald-100 text-emerald-800',
			pending: 'bg-amber-100 text-amber-800',
			in_progress: 'bg-blue-100 text-blue-800',
			completed: 'bg-green-100 text-green-800',
			client_cancelled: 'bg-red-100 text-red-800',
			we_cancelled: 'bg-rose-100 text-rose-800',
			no_show: 'bg-gray-100 text-gray-800',
			pending_release: 'bg-orange-100 text-orange-800',
			deposit_lapsed: 'bg-yellow-100 text-yellow-800'
		};
		return `${baseClasses} ${statusMap[status] || 'bg-gray-100 text-gray-800'}`;
	}

	function getStatusDotClasses(status: Booking['status']): string {
		const statusMap: Record<string, string> = {
			confirmed: 'bg-emerald-600',
			pending: 'bg-amber-600',
			in_progress: 'bg-blue-600',
			completed: 'bg-green-600',
			client_cancelled: 'bg-red-600',
			we_cancelled: 'bg-rose-600',
			no_show: 'bg-gray-600',
			pending_release: 'bg-orange-600',
			deposit_lapsed: 'bg-yellow-600'
		};
		return `mr-1 h-1.5 w-1.5 rounded-full ${statusMap[status] || 'bg-gray-600'}`;
	}
</script>

<Card.Root class="h-full">
	<Card.Header>
		<div class="flex items-start justify-between">
			<div>
				<Card.Title class="flex items-center gap-2">
					<svg
						xmlns="http://www.w3.org/2000/svg"
						class="h-5 w-5"
						viewBox="0 0 24 24"
						fill="none"
						stroke="currentColor"
						stroke-width="2"
					>
						<rect x="3" y="4" width="18" height="18" rx="2" ry="2" />
						<line x1="16" y1="2" x2="16" y2="6" />
						<line x1="8" y1="2" x2="8" y2="6" />
						<line x1="3" y1="10" x2="21" y2="10" />
					</svg>
					Bookings
				</Card.Title>
				<Card.Description>Search and manage booking history.</Card.Description>
			</div>

			<div class="rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium">
				<span class="text-xs font-semibold">{totalBookings}</span>
			</div>
		</div>
	</Card.Header>
	<Card.Content class="space-y-4">
		<div>
			<div class="flex gap-2">
				<Input
					placeholder="Search by customer name, email, phone, or service"
					bind:value={bookingQuery}
					onkeyup={(e) => {
						if ((e as KeyboardEvent).key === 'Enter') searchBookings();
					}}
				/>
				<Button onclick={() => searchBookings()} disabled={loadingSearch}>
					{loadingSearch ? 'Searching...' : 'Search'}
				</Button>
			</div>
			<div class="mt-3 max-h-60 space-y-2 overflow-y-auto">
				{#if bookings.length === 0 && !loadingSearch}
					<div class="text-center text-sm text-gray-500">No bookings found.</div>
				{:else if bookings.length > 0}
					<div class="space-y-2 {loadingSearch ? 'opacity-60' : ''}">
						{#each bookings as b (b.id)}
							<div class="flex items-center justify-between rounded bg-gray-50 p-2">
								<div class="flex-1">
									<div class="font-medium">
										{formatBookingDateTime(b.start_time)}
									</div>
									<div class="mt-1 flex items-center gap-2 text-xs text-gray-500">
										<span class={getStatusClasses(b.status)}>
											<span class={getStatusDotClasses(b.status)}></span>
											{b.status}
										</span>
										{#if b.deposit_required}
											{#if b.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 ['confirmed', 'in_progress', 'completed'].includes(b.status)}
												<span
													class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium
														{b.deposit_paid ? 'bg-green-100 text-green-800' : 'bg-orange-100 text-orange-800'}"
												>
													{b.deposit_paid ? 'Deposit Paid' : 'Deposit Due'}
												</span>
											{/if}
										{/if}
										<span
											>• {formatUserName(
												b.user?.full_name || 'Unknown User',
												b.user?.previous_first_name,
												b.user?.previous_last_name
											)}</span
										>
										<span>
											- {formatServices(b.services)}
										</span>
									</div>
								</div>
								<Button variant="outline" onclick={() => openBookingModal(b.id)}>View</Button>
							</div>
						{/each}
					</div>
				{/if}
			</div>

			{#if !initialLoad && totalPages > 1}
				<div class="mt-3 flex items-center justify-between border-t pt-3 text-sm">
					<Button
						variant="outline"
						size="sm"
						onclick={previousPage}
						disabled={currentPage === 1 || loadingSearch}
					>
						Previous
					</Button>
					<span class="text-xs text-gray-600">
						Page {currentPage} of {totalPages}
					</span>
					<Button
						variant="outline"
						size="sm"
						onclick={nextPage}
						disabled={currentPage === totalPages || loadingSearch}
					>
						Next
					</Button>
				</div>
			{/if}
		</div>
	</Card.Content>
</Card.Root>
