<script lang="ts">
	import { authStore } from '$lib/stores/auth.svelte';
	import { SvelteDate } 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 { Skeleton } from '$lib/components/ui/skeleton';

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

	// Types
	type Booking = {
		id: string;
		start_time: string;
		status:
			| 'pending'
			| 'confirmed'
			| 'in_progress'
			| 'completed'
			| 'client_cancelled'
			| 'we_cancelled'
			| 're-schedule'
			| 'no_show';
		notes?: string;
		created_at: string;
		updated_at: string;
		created_by?: string;
		user?: {
			id: string;
			full_name: string;
		};
		services: Array<{
			booking_id: string;
			service_id: string;
			override_price?: number;
			override_duration_minutes?: number;
			service_name?: string;
			service_description?: string;
			price?: number;
			duration_minutes?: number;
		}>;
		payments: Array<{
			id: string;
			booking_id: string;
			payment_type: 'deposit' | 'full' | 'tip' | 'balance' | 'partial';
			payment_method: 'online_square' | 'in_person_card' | 'cash' | 'giftcard' | 'discount';
			vendor_code?: string;
			invoice_number?: number;
			status: 'pending' | 'completed' | 'failed' | 'refunded';
			amount: number;
			is_vat_applicable: boolean;
			vat_rate?: number;
			vat_amount?: number;
			net_amount?: number;
			created_at: string;
			updated_at: string;
			created_by?: string;
		}>;
		total_amount: number;
		amount_paid: number;
		amount_due: number;
		duration_minutes: number;
	};

	// State
	let bookings = $state<Booking[]>([]);
	let bookingQuery = $state('');
	let loadingSearch = $state(false);

	// Fetch bookings from API
	async function fetchBookings() {
		loadingSearch = true;
		try {
			const response = await fetch('/api/admin/bookings', {
				method: 'GET',
				headers: {
					'Content-Type': 'application/json',
					Authorization: `Bearer ${authStore.currentToken}`
				}
			});
			if (response.ok) {
				const data = await response.json();

				if (data.bookings && data.bookings.length === 0) {
					bookings = [];
					return;
				}

				bookings = data.bookings.map((b: any) => ({
					id: b.id,
					start_time: b.start_time,
					status: b.status,
					notes: b.notes,
					created_at: b.created_at,
					updated_at: b.updated_at,
					created_by: b.created_by,
					user: b.user
						? {
								id: b.user.id,
								full_name: b.user.full_name
							}
						: undefined,
					services: b.services || [],
					total_amount: b.total_amount || 0,
					amount_paid: b.amount_paid || 0,
					amount_due: b.amount_due || 0,
					duration_minutes: b.duration_minutes || 0
				}));
			} 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;
		}
	}

	// Search bookings via API
	async function searchBookings() {
		loadingSearch = true;

		if (!bookingQuery.trim()) {
			await fetchBookings();
			loadingSearch = false;
			return;
		}

		try {
			const response = await fetch(
				`/api/admin/bookings/search?q=${encodeURIComponent(bookingQuery)}`,
				{
					headers: {
						Authorization: `Bearer ${authStore.currentToken}`
					}
				}
			);

			// HTTP error (400 / 401 / 500 etc)
			if (!response.ok) {
				const message = await response.text();
				throw new Error(message || `Request failed (${response.status})`);
			}

			const data = await response.json();
			const bookingsData = Array.isArray(data.bookings) ? data.bookings : [];

			bookings = bookingsData.map((b: any) => ({
				id: b.id,
				start_time: b.start_time,
				status: b.status,
				notes: b.notes,
				created_at: b.created_at,
				updated_at: b.updated_at,
				created_by: b.created_by,
				user: b.user ? { id: b.user.id, full_name: b.user.full_name } : undefined,
				services: b.services || [],
				total_amount: b.total_amount || 0,
				amount_paid: b.amount_paid || 0,
				amount_due: b.amount_due || 0,
				duration_minutes: b.duration_minutes || 0
			}));
		} catch (err) {
			console.error('Search bookings failed:', err);

			toast.error(err instanceof Error ? err.message : 'Unexpected error searching bookings');
		} finally {
			loadingSearch = false;
		}
	}

	// 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 = {
			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',
			're-schedule': 'bg-purple-100 text-purple-800',
			no_show: 'bg-gray-100 text-gray-800'
		};
		return `${baseClasses} ${statusMap[status] || 'bg-gray-100 text-gray-800'}`;
	}

	function getStatusDotClasses(status: Booking['status']): string {
		const statusMap = {
			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',
			're-schedule': 'bg-purple-600',
			no_show: 'bg-gray-600'
		};
		return `mr-1 h-1.5 w-1.5 rounded-full ${statusMap[status] || 'bg-gray-600'}`;
	}

	// Fetch bookings on mount
	$effect(() => {
		fetchBookings();
	});
</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>
	</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 loadingSearch}
					<div class="flex items-center justify-center p-4">
						<Skeleton class="h-4 w-32" />
					</div>
				{:else if bookings.length === 0}
					<div class="text-center text-sm text-gray-500">No bookings found.</div>
				{:else}
					{#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>
									<span>• {b.user?.full_name || 'Unknown User'}</span>
									<span>
										- {formatServices(b.services)}
									</span>
								</div>
							</div>
							<Button variant="outline" onclick={() => openBookingModal(b.id)}>View</Button>
						</div>
					{/each}
				{/if}
			</div>
		</div>
	</Card.Content>
</Card.Root>
