'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;
}

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

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 [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();
	}, []);

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

	// 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',
			});
		}
	};

	const fetchBookings = async () => {
		try {
			const response = await fetch('/api/bookings');
			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[] => {
		if (!settings) return [];

		const start = parseInt(settings.booking_start_time.split(':')[0]);
		const end = parseInt(settings.booking_end_time.split(':')[0]);
		const slots = [];

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

		return slots;
	};

	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'
				);

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

		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;

		// Check weekend restrictions
		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;

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

	const handleBookingConfirm = async () => {
		if (!selectedSlot) 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) => (
										<Button
											key={index}
											variant={
												date.toDateString() === selectedDate.toDateString()
													? 'default'
													: 'outline'
											}
											size='sm'
											onClick={() => setSelectedDate(date)}
											className='h-16 flex flex-col'
										>
											<span className='text-xs font-normal'>
												{date.toLocaleDateString('en-US', { weekday: 'short' })}
											</span>
											<span className='font-semibold'>{date.getDate()}</span>
											<span className='text-xs font-normal'>
												{date.toLocaleDateString('en-US', { month: 'short' })}
											</span>
											{isToday(date) && <span className='text-xs text-blue-600'>Today</span>}
										</Button>
									))}
							</div>
						</div>

						{/* Selected Date Display */}
						<div className='text-center p-4 bg-blue-50 rounded-lg'>
							<h3 className='text-lg font-semibold text-blue-900'>
								{selectedDate.toLocaleDateString('en-US', {
									weekday: 'long',
									year: 'numeric',
									month: 'long',
									day: 'numeric',
								})}
							</h3>
							{isToday(selectedDate) && <span className='text-sm text-blue-600'>Today</span>}
						</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-gray-900'></div>
								<p className='mt-2 text-sm text-gray-500'>Loading booking slots...</p>
							</div>
						)}

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

						{/* Time Slots Grid */}
						{!loading && courts.length > 0 && (
							<div className='space-y-4'>
								<h3 className='font-medium'>Available Time Slots</h3>
								<div className='grid grid-cols-1 sm:grid-cols-2 gap-4'>
									{bookingSlots.map((slot, index) => (
										<div
											key={`${slot.courtId}-${slot.time}`}
											className={`p-4 border rounded-lg transition-colors cursor-pointer ${
												slot.available
													? 'border-green-200 bg-green-50 hover:bg-green-100'
													: 'border-red-200 bg-red-50 cursor-not-allowed'
											}`}
											onClick={() => handleSlotClick(slot)}
										>
											<div className='flex items-center justify-between'>
												<div className='space-y-2'>
													<div className='flex items-center gap-2 text-sm font-medium'>
														<Clock className='h-4 w-4' />
														{slot.time} -{' '}
														{String(parseInt(slot.time.split(':')[0]) + 1).padStart(2, '0')}
														:00
													</div>
													<div className='flex items-center gap-2 text-sm text-gray-600'>
														<MapPin className='h-4 w-4' />
														{slot.courtName}
													</div>
													{!slot.available && (
														<div className='text-xs text-red-600'>Already booked</div>
													)}
												</div>
												<Button
													size='sm'
													disabled={!slot.available}
													className={slot.available ? 'bg-green-600 hover:bg-green-700' : ''}
												>
													{slot.available ? 'Book' : 'Booked'}
												</Button>
											</div>
										</div>
									))}
								</div>
							</div>
						)}

						{/* No Slots Message */}
						{!loading && courts.length > 0 && bookingSlots.length === 0 && (
							<div className='text-center py-8'>
								<p className='text-gray-500'>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-blue-50 p-4 rounded-lg space-y-2'>
								<div className='flex items-center gap-2 text-sm'>
									<Calendar className='h-4 w-4' />
									{selectedDate.toLocaleDateString('en-US', {
										weekday: 'long',
										month: 'long',
										day: 'numeric',
									})}
								</div>
								<div className='flex items-center gap-2 text-sm'>
									<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'>
									<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-gray-400' />
								<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-gray-500'>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>
	);
}
