<script lang="ts">
	import { Button } from '$lib/components/ui/button';
	import WalkInCreateModal from '$lib/components/admin/WalkInCreateModal.svelte';
	import { authStore } from '$lib/stores/auth.svelte';
	import { CalendarDate } from '@internationalized/date';
	import { SvelteDate } from 'svelte/reactivity';
	import { onMount } from 'svelte';
	import { toast } from 'svelte-sonner';

	import type { AvailableHoursDay } from '$lib/types/booking';

	let showCreateModal = $state(false);
	let slotInfo = $state<{
		isAvailableNow: boolean;
		waitMinutes?: number;
		durationMinutes: number;
		startTime?: string;
		slotEndMinutes?: number;
	} | null>(null);
	let loading = $state(true);
	let noSlotsToday = $state(false);
	let currentTime = $state(new Date());

	// Reservation state for walk-in
	let reservationId = $state<string | null>(null);
	let reservationExpiresAt = $state<Date | null>(null);
	let reservationCountdown = $state<string>('');
	let isReserving = $state(false);

	onMount(() => {
		calculateSlotAvailability();

		// Update current time every minute for live countdown
		const interval = setInterval(() => {
			currentTime = new Date();
		}, 60000); // Update every minute

		return () => clearInterval(interval);
	});

	/**
	 * Converts "HH:MM" or "HH:MM:SS" time string to minutes since midnight
	 */
	function timeToMinutes(time: string): number {
		const parts = time.split(':').map(Number);
		return parts[0] * 60 + parts[1];
	}

	/**
	 * Converts minutes to hours and minutes for display
	 */
	function formatDuration(minutes: number): string {
		const hours = Math.floor(minutes / 60);
		const mins = minutes % 60;

		if (hours > 0 && mins > 0) {
			return `${hours} hour${hours !== 1 ? 's' : ''}, ${mins} minute${mins !== 1 ? 's' : ''}`;
		} else if (hours > 0) {
			return `${hours} hour${hours !== 1 ? 's' : ''}`;
		} else {
			return `${mins} minute${mins !== 1 ? 's' : ''}`;
		}
	}

	/**
	 * Calculate live remaining time based on current time
	 */
	function getLiveRemainingMinutes(): number | null {
		if (!slotInfo?.isAvailableNow || !slotInfo.slotEndMinutes) return null;

		const now = currentTime.getHours() * 60 + currentTime.getMinutes();
		const remaining = slotInfo.slotEndMinutes - now;
		return Math.max(0, remaining);
	}

	/**
	 * Calculate live wait time based on current time
	 */
	function getLiveWaitMinutes(): number | null {
		if (slotInfo?.isAvailableNow || !slotInfo?.startTime) return null;

		const now = currentTime.getHours() * 60 + currentTime.getMinutes();
		const slotStartMinutes = timeToMinutes(slotInfo.startTime);
		const wait = slotStartMinutes - now;
		return Math.max(0, wait);
	}

	async function calculateSlotAvailability() {
		loading = true;
		noSlotsToday = false;

		try {
			const now = new SvelteDate();
			const today = new CalendarDate(now.getFullYear(), now.getMonth() + 1, now.getDate());

			// Fetch today's available hours
			const response = await fetch(`/api/scheduling/available-hours?start=${today}&end=${today}`, {
				headers: { Authorization: `Bearer ${authStore.currentToken}` }
			});

			if (!response.ok) {
				noSlotsToday = true;
				return;
			}

			const data: AvailableHoursDay[] = await response.json();
			const todayData = data[0];

			if (!todayData || !todayData.isOpen || !todayData.slots || todayData.slots.length === 0) {
				noSlotsToday = true;
				return;
			}

			// Current time in minutes since midnight
			const currentMinutes = now.getHours() * 60 + now.getMinutes();

			// Check if we're currently in an available slot
			for (const slot of todayData.slots) {
				const slotStartMinutes = timeToMinutes(slot.startTime);
				const slotEndMinutes = timeToMinutes(slot.endTime);

				// Are we currently within this slot?
				if (currentMinutes >= slotStartMinutes && currentMinutes < slotEndMinutes) {
					const remainingMinutes = slotEndMinutes - currentMinutes;
					slotInfo = {
						isAvailableNow: true,
						durationMinutes: remainingMinutes,
						slotEndMinutes: slotEndMinutes // Store for live countdown
					};
					return;
				}

				// Is this a future slot?
				if (slotStartMinutes > currentMinutes) {
					const waitMinutes = slotStartMinutes - currentMinutes;
					const durationMinutes = slotEndMinutes - slotStartMinutes;
					slotInfo = {
						isAvailableNow: false,
						waitMinutes,
						durationMinutes,
						startTime: slot.startTime
					};
					return;
				}
			}

			// No current or future slots available
			noSlotsToday = true;
		} catch (err) {
			console.error('Failed to calculate slot availability', err);
			noSlotsToday = true;
		} finally {
			loading = false;
		}
	}

	function formatTime(time: string): string {
		const [hours, minutes] = time.split(':').map(Number);
		const period = hours >= 12 ? 'PM' : 'AM';
		const displayHours = hours % 12 || 12;
		return `${displayHours}:${minutes.toString().padStart(2, '0')} ${period}`;
	}

	async function reserveWalkInSlot(startTime: string): Promise<boolean> {
		isReserving = true;

		try {
			const now = new SvelteDate();
			const [hours, minutes] = startTime.split(':').map(Number);
			const start = new SvelteDate(
				now.getFullYear(),
				now.getMonth(),
				now.getDate(),
				hours,
				minutes,
				0,
				0
			);
			const startTimeISO = start.toISOString();

			const response = await fetch('/api/admin/bookings/reserve', {
				method: 'POST',
				headers: {
					'Content-Type': 'application/json',
					Authorization: `Bearer ${authStore.currentToken}`
				},
				body: JSON.stringify({
					user_id: null,
					start_time: startTimeISO,
					service_ids: [],
					service_overrides: [],
					ttl_minutes: 5
				})
			});

			if (response.ok) {
				const data = await response.json();
				reservationId = data.id;
				reservationExpiresAt = new Date(data.expires_at);
				startWalkInCountdown();
				return true;
			} else if (response.status === 409) {
				toast.error('Slot no longer available, please try again');
				calculateSlotAvailability();
				return false;
			} else {
				const errorText = await response.text();
				toast.error(`Failed to reserve slot: ${errorText}`);
				return false;
			}
		} catch (err) {
			console.error('Reservation error:', err);
			toast.error('Failed to reserve slot');
			return false;
		} finally {
			isReserving = false;
		}
	}

	function startWalkInCountdown() {
		if ((window as any).__walkInCountdownInterval) {
			clearInterval((window as any).__walkInCountdownInterval);
		}

		const updateCountdown = () => {
			if (!reservationExpiresAt) {
				reservationCountdown = '';
				return;
			}

			const now = new Date();
			const diff = reservationExpiresAt.getTime() - now.getTime();

			if (diff <= 0) {
				reservationCountdown = 'Expired';
				reservationId = null;
				reservationExpiresAt = null;
				toast.error('Slot released — please re-check availability');
				if ((window as any).__walkInCountdownInterval) {
					clearInterval((window as any).__walkInCountdownInterval);
				}
				showCreateModal = false;
				return;
			}

			const minutes = Math.floor(diff / 60000);
			const seconds = Math.floor((diff % 60000) / 1000);
			reservationCountdown = `${minutes}:${seconds.toString().padStart(2, '0')}`;
		};

		updateCountdown();
		(window as any).__walkInCountdownInterval = setInterval(updateCountdown, 1000);
	}

	function handleStartWalkIn() {
		if (slotInfo?.isAvailableNow) {
			showCreateModal = true;
		} else if (slotInfo?.startTime) {
			reserveWalkInSlot(slotInfo.startTime).then((reserved) => {
				if (reserved) {
					showCreateModal = true;
				}
			});
		}
	}

	function handleModalClose() {
		showCreateModal = false;
		reservationId = null;
		reservationExpiresAt = null;
		reservationCountdown = '';
		if ((window as any).__walkInCountdownInterval) {
			clearInterval((window as any).__walkInCountdownInterval);
		}
	}
</script>

<div class="rounded-lg border border-gray-200 bg-white p-4">
	<h3 class="mb-2 text-sm font-semibold tracking-wide text-gray-600 uppercase">Walk-In Booking</h3>

	{#if loading}
		<div class="mb-4 h-12 animate-pulse rounded bg-gray-100"></div>
	{:else if noSlotsToday}
		<p class="mb-4 text-sm text-gray-500">No slots available for walk-in today</p>
	{:else if slotInfo?.isAvailableNow}
		{@const liveRemaining = getLiveRemainingMinutes()}
		{#if liveRemaining !== null && liveRemaining > 0}
			<p class="mb-4 text-sm text-gray-500">
				Available now for <span class="font-semibold text-gray-700"
					>{formatDuration(liveRemaining)}</span
				>
			</p>
		{:else}
			<p class="mb-4 text-sm text-gray-500">No slots available for walk-in today</p>
		{/if}
	{:else if slotInfo && !slotInfo.isAvailableNow}
		{@const liveWait = getLiveWaitMinutes()}
		{#if liveWait !== null && liveWait > 0}
			<p class="mb-4 text-sm text-gray-500">
				Next slot available in <span class="font-semibold text-gray-700"
					>{formatDuration(liveWait)}</span
				>
				at {formatTime(slotInfo.startTime!)}, for
				<span class="font-semibold text-gray-700">{formatDuration(slotInfo.durationMinutes)}</span>
			</p>
		{:else}
			<p class="mb-4 text-sm text-gray-500">
				Available now for <span class="font-semibold text-gray-700"
					>{formatDuration(slotInfo.durationMinutes)}</span
				>
			</p>
		{/if}
	{/if}

	<div class="flex items-center gap-3">
		<Button
			onclick={handleStartWalkIn}
			disabled={noSlotsToday || isReserving || (slotInfo?.isAvailableNow && (getLiveRemainingMinutes() ?? 0) <= 0)}
		>
			{isReserving ? 'Reserving...' : 'Start Walk-In Session'}
		</Button>
	</div>
</div>

{#if showCreateModal}
	<WalkInCreateModal
		bind:open={showCreateModal}
		maxSlotDuration={slotInfo?.durationMinutes ?? 0}
		availableStartTime={slotInfo?.isAvailableNow ? undefined : slotInfo?.startTime}
		reservationExpiresAt={reservationExpiresAt}
		onclose={handleModalClose}
	/>
{/if}
