'use client';

import { useState, useEffect } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
import { Calendar, Clock, MapPin, ChevronLeft, ChevronRight, Users, User } from 'lucide-react';
import { useToast } from '@/hooks/use-toast';

interface Court {
	id: string;
	name: string;
	isActive: boolean;
}

interface Booking {
	id: string;
	courtId: string;
	date: string;
	startTime: string;
	endTime: string;
	status: string;
	userId: string;
	notes?: string;
	user?: {
		id: string;
		name: string;
		surname: string;
	};
}

interface BookingSlot {
	time: string;
	courtId: string;
	courtName: string;
	available: boolean;
	bookingId?: string;
	bookedBy?: string;
	partner?: string;
}

interface TimeSlot {
	id: string;
	dayOfWeek: number;
	startTime: string;
	endTime: string;
	isActive: boolean;
}

interface Settings {
	booking_window_days: string;
	booking_start_time: string;
	booking_end_time: string;
	allow_weekend_bookings: string;
}

export function EnhancedBookingCalendar() {
	const [selectedDate, setSelectedDate] = useState(new Date());
	const [courts, setCourts] = useState<Court[]>([]);
	const [bookings, setBookings] = useState<Booking[]>([]);
	const [bookingSlots, setBookingSlots] = useState<BookingSlot[]>([]);
	const [timeSlots, setTimeSlots] = useState<TimeSlot[]>([]);
	const [settings, setSettings] = useState<Settings | null>(null);
	const [loading, setLoading] = useState(false);
	const [partnerName, setPartnerName] = useState('');
	const [notes, setNotes] = useState('');
	const [showBookingDialog, setShowBookingDialog] = useState(false);
	const [selectedSlot, setSelectedSlot] = useState<BookingSlot | null>(null);
	const { toast } = useToast();

	useEffect(() => {
		fetchSettings();
		fetchCourts();
		fetchTimeSlots();
	}, []);

	useEffect(() => {
		if (courts.length > 0 && timeSlots.length > 0) {
			fetchBookings();
		}
	}, [selectedDate, courts, timeSlots]);

	// Fetch settings from public endpoint (not admin)
	const fetchSettings = async () => {
		try {
			const response = await fetch('/api/settings');
			if (response.ok) {
				const data = await response.json();
				const settingsMap: Settings = {
					booking_window_days: '7',
					booking_start_time: '08:00',
					booking_end_time: '22:00',
					allow_weekend_bookings: 'true',
				};

				data.settings.forEach((setting: any) => {
					if (setting.key in settingsMap) {
						settingsMap[setting.key as keyof Settings] = setting.value;
					}
				});

				setSettings(settingsMap);
			} else {
				// If settings fetch fails, use defaults
				setSettings({
					booking_window_days: '7',
					booking_start_time: '08:00',
					booking_end_time: '22:00',
					allow_weekend_bookings: 'true',
				});
			}
		} catch (error) {
			console.error('Error fetching settings:', error);
			// Set default settings
			setSettings({
				booking_window_days: '7',
				booking_start_time: '08:00',
				booking_end_time: '22:00',
				allow_weekend_bookings: 'true',
			});
		}
	};

	// Fetch courts from public endpoint (not admin)
	const fetchCourts = async () => {
		try {
			const response = await fetch('/api/courts');
			if (response.ok) {
				const data = await response.json();
				setCourts(data.courts.filter((court: Court) => court.isActive));
			}
		} catch (error) {
			console.error('Error fetching courts:', error);
			toast({
				title: 'Error',
				description: 'Failed to fetch courts',
				variant: 'destructive',
			});
		}
	};

	// Fetch time slots for day-specific booking times
	const fetchTimeSlots = async () => {
		try {
			const response = await fetch('/api/time-slots');
			if (response.ok) {
				const data = await response.json();
				setTimeSlots(data.timeSlots);
			}
		} catch (error) {
			console.error('Error fetching time slots:', error);
			// If time slots fetch fails, we'll use fallback settings
		}
	};

	const fetchBookings = async () => {
		try {
			const dateStr = selectedDate.toISOString().split('T')[0];
			const response = await fetch(`/api/bookings/all?date=${dateStr}`);
			if (response.ok) {
				const data = await response.json();
				setBookings(data.bookings);
				generateBookingSlots(data.bookings);
			}
		} catch (error) {
			console.error('Error fetching bookings:', error);
			toast({
				title: 'Error',
				description: 'Failed to fetch bookings',
				variant: 'destructive',
			});
		}
	};

	const generateTimeSlots = (): string[] => {
		const dayOfWeek = selectedDate.getDay();

		// Get time slots for the selected day
		const dayTimeSlots = timeSlots.filter((slot) => slot.dayOfWeek === dayOfWeek && slot.isActive);

		if (dayTimeSlots.length > 0) {
			// Use day-specific time slots
			const slots: string[] = [];
			dayTimeSlots.forEach((timeSlot) => {
				const start = parseInt(timeSlot.startTime.split(':')[0]);
				const end = parseInt(timeSlot.endTime.split(':')[0]);

				for (let hour = start; hour < end; hour++) {
					slots.push(`${hour.toString().padStart(2, '0')}:00`);
				}
			});

			// Remove duplicates and sort
			return [...new Set(slots)].sort();
		}

		// NO FALLBACK - If no day-specific time slots, return empty array
		// This prevents booking on days where no play is scheduled
		return [];
	};

	const isDayBookable = (): boolean => {
		const dayOfWeek = selectedDate.getDay();
		const dayTimeSlots = timeSlots.filter((slot) => slot.dayOfWeek === dayOfWeek && slot.isActive);
		return dayTimeSlots.length > 0;
	};

	const getDayName = (dayOfWeek: number): string => {
		const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
		return days[dayOfWeek];
	};

	const parseBookingNotes = (notes?: string) => {
		if (!notes) return { partner: '', additionalNotes: '' };

		const parts = notes.split(' | ');
		let partner = '';
		let additionalNotes = '';

		parts.forEach((part) => {
			if (part.startsWith('Partner: ')) {
				partner = part.replace('Partner: ', '');
			} else {
				additionalNotes = additionalNotes ? `${additionalNotes} | ${part}` : part;
			}
		});

		return { partner, additionalNotes };
	};

	const generateBookingSlots = (existingBookings: Booking[]) => {
		const dateStr = selectedDate.toISOString().split('T')[0];
		const timeSlots = generateTimeSlots();
		const slots: BookingSlot[] = [];

		courts.forEach((court) => {
			timeSlots.forEach((time) => {
				const existingBooking = existingBookings.find(
					(booking) =>
						booking.courtId === court.id &&
						booking.date === dateStr &&
						booking.startTime === time &&
						booking.status === 'active'
				);

				const bookedBy = existingBooking?.user
					? `${existingBooking.user.name} ${existingBooking.user.surname}`
					: undefined;

				const { partner } = parseBookingNotes(existingBooking?.notes);

				slots.push({
					time,
					courtId: court.id,
					courtName: court.name,
					available: !existingBooking,
					bookingId: existingBooking?.id,
					bookedBy,
					partner,
				});
			});
		});

		setBookingSlots(slots);
	};

	const isDateSelectable = (date: Date): boolean => {
		if (!settings) return false;

		const today = new Date();
		today.setHours(0, 0, 0, 0);

		const selectedDateOnly = new Date(date);
		selectedDateOnly.setHours(0, 0, 0, 0);

		// Check if date is in the past
		if (selectedDateOnly < today) return false;

		// Check booking window
		const maxDate = new Date(today);
		maxDate.setDate(today.getDate() + parseInt(settings.booking_window_days));
		if (selectedDateOnly > maxDate) return false;

		// CRITICAL: Check if there are any active time slots for this day
		const dayOfWeek = selectedDateOnly.getDay();
		const dayTimeSlots = timeSlots.filter((slot) => slot.dayOfWeek === dayOfWeek && slot.isActive);

		// If no time slots are configured for this day, it's not selectable
		if (dayTimeSlots.length === 0) return false;

		// Legacy weekend restriction check (now superseded by time slot configuration)
		// Keep for backward compatibility if global settings still matter
		if (settings.allow_weekend_bookings === 'false') {
			const dayOfWeek = selectedDateOnly.getDay();
			if (dayOfWeek === 0 || dayOfWeek === 6) return false; // Sunday or Saturday
		}

		return true;
	};

	const handleSlotClick = (slot: BookingSlot) => {
		if (!slot.available) return;

		// Double-check that this day is actually bookable
		if (!isDayBookable()) {
			toast({
				title: 'Booking Not Available',
				description: `Courts are closed on ${getDayName(selectedDate.getDay())}s`,
				variant: 'destructive',
			});
			return;
		}

		setSelectedSlot(slot);
		setPartnerName('');
		setNotes('');
		setShowBookingDialog(true);
	};

	const handleBookingConfirm = async () => {
		if (!selectedSlot) return;

		// Final validation before API call
		if (!isDayBookable()) {
			toast({
				title: 'Booking Not Available',
				description: `Courts are closed on ${getDayName(selectedDate.getDay())}s`,
				variant: 'destructive',
			});
			setShowBookingDialog(false);
			return;
		}

		setLoading(true);
		try {
			const dateStr = selectedDate.toISOString().split('T')[0];
			const bookingNotes = [];

			if (partnerName.trim()) {
				bookingNotes.push(`Partner: ${partnerName.trim()}`);
			}
			if (notes.trim()) {
				bookingNotes.push(notes.trim());
			}

			const response = await fetch('/api/bookings', {
				method: 'POST',
				headers: {
					'Content-Type': 'application/json',
				},
				body: JSON.stringify({
					courtId: selectedSlot.courtId,
					date: dateStr,
					timeSlot: selectedSlot.time,
					notes: bookingNotes.join(' | '),
				}),
			});

			const data = await response.json();

			if (response.ok) {
				toast({
					title: 'Success',
					description: 'Booking created successfully!',
				});
				setShowBookingDialog(false);
				fetchBookings(); // Refresh bookings
			} else {
				toast({
					title: 'Error',
					description: data.error || 'Failed to create booking',
					variant: 'destructive',
				});
			}
		} catch (error) {
			console.error('Error booking slot:', error);
			toast({
				title: 'Error',
				description: 'Failed to create booking',
				variant: 'destructive',
			});
		} finally {
			setLoading(false);
		}
	};

	const navigateDate = (direction: 'prev' | 'next') => {
		const newDate = new Date(selectedDate);
		newDate.setDate(newDate.getDate() + (direction === 'next' ? 1 : -1));

		if (isDateSelectable(newDate)) {
			setSelectedDate(newDate);
		}
	};

	const getAvailableDates = (): Date[] => {
		if (!settings) return [];

		const dates: Date[] = [];
		const today = new Date();
		const maxDays = parseInt(settings.booking_window_days);

		for (let i = 0; i <= maxDays; i++) {
			const date = new Date(today);
			date.setDate(today.getDate() + i);

			if (isDateSelectable(date)) {
				dates.push(date);
			}
		}

		return dates;
	};

	const isPastDate = (date: Date) => {
		const today = new Date();
		today.setHours(0, 0, 0, 0);
		return date < today;
	};

	const isToday = (date: Date) => {
		const today = new Date();
		return date.toDateString() === today.toDateString();
	};

	if (!settings) {
		return (
			<Card>
				<CardContent className='p-6'>
					<div className='flex items-center justify-center'>
						<div className='animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900'></div>
						<p className='ml-2'>Loading booking system...</p>
					</div>
				</CardContent>
			</Card>
		);
	}

	return (
		<div className='space-y-6'>
			<Card>
				<CardHeader>
					<CardTitle className='flex items-center gap-2'>
						<Calendar className='h-5 w-5' />
						Book Your Court
					</CardTitle>
				</CardHeader>
				<CardContent>
					{/* Mobile-friendly date navigation */}
					<div className='space-y-6'>
						{/* Quick Date Selection */}
						<div className='space-y-4'>
							<h3 className='font-medium'>Select Date</h3>
							<div className='grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-2'>
								{getAvailableDates()
									.slice(0, 8)
									.map((date, index) => {
										const isSelectedDate = date.toDateString() === selectedDate.toDateString();
										const isTodayDate = isToday(date);

										return (
											<Button
												key={index}
												variant={isSelectedDate ? 'default' : 'outline'}
												size='sm'
												onClick={() => setSelectedDate(date)}
												className={`h-16 flex flex-col relative transition-all ${
													isSelectedDate && !isTodayDate
														? 'bg-primary text-primary-foreground hover:bg-primary/90'
														: ''
												} ${
													isTodayDate && !isSelectedDate
														? 'ring-2 ring-blue-400 ring-opacity-50 bg-blue-50 dark:bg-blue-950 border-blue-200 dark:border-blue-800 hover:bg-blue-100 dark:hover:bg-blue-900 text-foreground'
														: ''
												} ${
													isSelectedDate && isTodayDate
														? 'bg-gradient-to-r from-blue-600 to-blue-700 hover:from-blue-700 hover:to-blue-800 dark:from-blue-700 dark:to-blue-800 dark:hover:from-blue-800 dark:hover:to-blue-900 text-white'
														: ''
												}`}
											>
												{isTodayDate && (
													<div className='absolute -top-1 -right-1 w-3 h-3 bg-orange-500 dark:bg-orange-400 rounded-full animate-pulse' />
												)}
												<span className='text-xs font-normal'>
													{date.toLocaleDateString('en-IE', { weekday: 'short' })}
												</span>
												<span className='font-semibold'>{date.getDate()}</span>
												<span className='text-xs font-normal'>
													{date.toLocaleDateString('en-IE', { month: 'short' })}
												</span>
											</Button>
										);
									})}
							</div>
						</div>

						{/* Selected Date Display */}
						<div
							className={`text-center p-4 rounded-lg ${
								isToday(selectedDate)
									? 'bg-gradient-to-r from-blue-500 to-indigo-600 text-white dark:from-blue-600 dark:to-indigo-700'
									: 'bg-blue-50 dark:bg-blue-950'
							}`}
						>
							<h3
								className={`text-lg font-semibold ${
									isToday(selectedDate) ? 'text-primary-foreground' : 'text-foreground'
								}`}
							>
								{selectedDate.toLocaleDateString('en-IE', {
									weekday: 'long',
									year: 'numeric',
									month: 'long',
									day: 'numeric',
								})}
							</h3>
							{isToday(selectedDate) && (
								<div className='flex items-center justify-center gap-2 mt-2'>
									<div className='w-2 h-2 bg-orange-300 dark:bg-orange-400 rounded-full animate-pulse' />
									<span className='text-sm font-medium text-blue-100 dark:text-blue-200'>Today</span>
									<div className='w-2 h-2 bg-orange-300 dark:bg-orange-400 rounded-full animate-pulse' />
								</div>
							)}
						</div>

						{/* Loading State */}
						{loading && (
							<div className='text-center py-8'>
								<div className='inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-primary'></div>
								<p className='mt-2 text-sm text-muted-foreground'>Loading booking slots...</p>
							</div>
						)}

						{/* No Courts Available */}
						{!loading && courts.length === 0 && (
							<div className='text-center py-8'>
								<p className='text-muted-foreground'>No courts available for booking</p>
							</div>
						)}

						{/* Time Slots Grid - Organized by Time */}
						{!loading && courts.length > 0 && (
							<div className='space-y-4'>
								<h3 className='font-medium'>Available Time Slots</h3>
								<div className='space-y-3'>
									{/* Group slots by time */}
									{Array.from(new Set(bookingSlots.map((slot) => slot.time)))
										.sort()
										.map((time) => {
											const slotsForTime = bookingSlots.filter((slot) => slot.time === time);

											return (
												<div key={time} className='space-y-2'>
													<div className='flex items-center gap-2 text-sm font-medium text-foreground'>
														<Clock className='h-4 w-4' />
														{time} -{' '}
														{String(parseInt(time.split(':')[0]) + 1).padStart(2, '0')}:00
													</div>
													<div
														className={`grid gap-3 ${
															slotsForTime.length === 1
																? 'grid-cols-1'
																: 'grid-cols-1 sm:grid-cols-2'
														}`}
													>
														{slotsForTime.map((slot) => (
															<div
																key={`${slot.courtId}-${slot.time}`}
																className={`p-3 border rounded-lg transition-all duration-200 ${
																	slot.available
																		? 'border-green-200 bg-green-50 hover:bg-green-100 hover:shadow-sm cursor-pointer dark:border-green-700 dark:bg-green-950 dark:hover:bg-green-900'
																		: 'border-muted bg-muted/50 cursor-not-allowed opacity-75 hover:opacity-100'
																}`}
																onClick={() => handleSlotClick(slot)}
															>
																<div className='flex items-center justify-between'>
																	<div className='space-y-1 flex-1'>
																		<div className='flex items-center gap-2 text-sm font-medium text-foreground'>
																			<MapPin className='h-4 w-4' />
																			{slot.courtName}
																		</div>
																		{!slot.available && slot.bookedBy && (
																			<div className='space-y-1'>
																				<div className='flex items-center gap-2 text-xs text-muted-foreground'>
																					<Users className='h-3 w-3' />
																					Booked by {slot.bookedBy}
																				</div>
																				{slot.partner && (
																					<div className='flex items-center gap-2 text-xs text-orange-600 dark:text-orange-400'>
																						<User className='h-3 w-3' />
																						Playing with: {slot.partner}
																					</div>
																				)}
																			</div>
																		)}
																		{!slot.available && !slot.bookedBy && (
																			<div className='text-xs text-muted-foreground'>
																				Already booked
																			</div>
																		)}
																	</div>
																	<Button
																		size='sm'
																		disabled={!slot.available}
																		variant={
																			slot.available ? 'default' : 'secondary'
																		}
																		className={
																			slot.available
																				? 'bg-green-600 hover:bg-green-700 dark:bg-green-700 dark:hover:bg-green-600 border-0'
																				: 'opacity-50 cursor-not-allowed'
																		}
																	>
																		{slot.available ? 'Book' : 'Booked'}
																	</Button>
																</div>
															</div>
														))}
													</div>
												</div>
											);
										})}
								</div>
							</div>
						)}

						{/* No Slots Message */}
						{!loading && courts.length > 0 && bookingSlots.length === 0 && (
							<div className='text-center py-8'>
								{!isDayBookable() ? (
									<div className='space-y-2'>
										<div className='text-destructive font-medium'>
											No courts available on {getDayName(selectedDate.getDay())}s
										</div>
										<p className='text-muted-foreground text-sm'>
											This facility is closed on {getDayName(selectedDate.getDay())}s. Please
											select a different day to make a booking.
										</p>
									</div>
								) : (
									<p className='text-muted-foreground'>No booking slots available for this date</p>
								)}
							</div>
						)}
					</div>
				</CardContent>
			</Card>

			{/* Booking Dialog */}
			<Dialog open={showBookingDialog} onOpenChange={setShowBookingDialog}>
				<DialogContent className='sm:max-w-md'>
					<DialogHeader>
						<DialogTitle>Confirm Your Booking</DialogTitle>
					</DialogHeader>
					<div className='space-y-4'>
						{selectedSlot && (
							<div className='bg-primary/5 border border-primary/20 p-4 rounded-lg space-y-2 dark:bg-primary/10 dark:border-primary/30'>
								<div className='flex items-center gap-2 text-sm text-foreground'>
									<Calendar className='h-4 w-4' />
									{selectedDate.toLocaleDateString('en-IE', {
										weekday: 'long',
										month: 'long',
										day: 'numeric',
									})}
								</div>
								<div className='flex items-center gap-2 text-sm text-foreground'>
									<Clock className='h-4 w-4' />
									{selectedSlot.time} -{' '}
									{String(parseInt(selectedSlot.time.split(':')[0]) + 1).padStart(2, '0')}:00
								</div>
								<div className='flex items-center gap-2 text-sm text-foreground'>
									<MapPin className='h-4 w-4' />
									{selectedSlot.courtName}
								</div>
							</div>
						)}

						<div className='space-y-2'>
							<Label htmlFor='partner'>Playing Partner (Optional)</Label>
							<div className='relative'>
								<User className='absolute left-3 top-3 h-4 w-4 text-muted-foreground' />
								<Input
									id='partner'
									placeholder='Who will you be playing with?'
									value={partnerName}
									onChange={(e) => setPartnerName(e.target.value)}
									className='pl-10'
								/>
							</div>
							<p className='text-xs text-muted-foreground'>
								Enter the name of the person you'll be playing with
							</p>
						</div>

						<div className='space-y-2'>
							<Label htmlFor='notes'>Additional Notes (Optional)</Label>
							<Textarea
								id='notes'
								placeholder='Any additional information...'
								value={notes}
								onChange={(e) => setNotes(e.target.value)}
								className='min-h-[80px]'
							/>
						</div>

						<div className='flex gap-2 pt-4'>
							<Button variant='outline' className='flex-1' onClick={() => setShowBookingDialog(false)}>
								Cancel
							</Button>
							<Button className='flex-1' onClick={handleBookingConfirm} disabled={loading}>
								{loading ? 'Booking...' : 'Confirm Booking'}
							</Button>
						</div>
					</div>
				</DialogContent>
			</Dialog>
		</div>
	);
}
