"use client";

import { useState, useEffect, useCallback } from "react";
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { TimeSlot } from "./time-slot";
import { cn, formatDate } from "@/lib/utils";

// Types for API responses
interface Site {
  id: string;
  name: string;
  slug: string;
  openTime: string;
  closeTime: string;
  timezone: string;
}

interface Court {
  id: string;
  name: string;
  type: string;
  status: string;
  pricePerHour: number;
  isActive: boolean;
  site: Site;
}

interface Slot {
  time: string;
  available: boolean;
  price: number;
  bookingId?: string;
  clientName?: string;
}

interface CourtAvailability {
  court: {
    id: string;
    name: string;
    type: string;
    status: string;
    isActive: boolean;
    site: Site;
  };
  date: string;
  slots: Slot[];
}

export interface SelectedSlot {
  courtId: string;
  courtName: string;
  date: string;
  time: string;
  available: boolean;
  price: number;
  bookingId?: string;
}

interface BookingCalendarProps {
  siteId?: string;
  onSlotClick?: (slot: SelectedSlot) => void;
}

export function BookingCalendar({ siteId, onSlotClick }: BookingCalendarProps) {
  const [date, setDate] = useState<Date>(() => {
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    return today;
  });
  const [courts, setCourts] = useState<Court[]>([]);
  const [availability, setAvailability] = useState<Map<string, CourtAvailability>>(
    new Map()
  );
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  // Format date as YYYY-MM-DD for API
  const formatDateForApi = (d: Date): string => {
    const year = d.getFullYear();
    const month = String(d.getMonth() + 1).padStart(2, "0");
    const day = String(d.getDate()).padStart(2, "0");
    return `${year}-${month}-${day}`;
  };

  // Fetch courts
  const fetchCourts = useCallback(async () => {
    try {
      const url = siteId ? `/api/courts?siteId=${siteId}` : "/api/courts";
      const response = await fetch(url);
      if (!response.ok) {
        throw new Error("Error loading courts");
      }
      const data = await response.json();
      setCourts(data);
      return data as Court[];
    } catch (err) {
      setError(err instanceof Error ? err.message : "Unknown error");
      return [];
    }
  }, [siteId]);

  // Fetch availability for a court
  const fetchCourtAvailability = useCallback(
    async (courtId: string, dateStr: string) => {
      try {
        const response = await fetch(
          `/api/courts/${courtId}/availability?date=${dateStr}`
        );
        if (!response.ok) {
          throw new Error(`Error loading availability`);
        }
        return (await response.json()) as CourtAvailability;
      } catch (err) {
        console.error(`Error fetching availability for court ${courtId}:`, err);
        return null;
      }
    },
    []
  );

  // Fetch all availability
  const fetchAllAvailability = useCallback(
    async (courtsList: Court[], dateStr: string) => {
      setLoading(true);
      const newAvailability = new Map<string, CourtAvailability>();

      const promises = courtsList.map(async (court) => {
        const avail = await fetchCourtAvailability(court.id, dateStr);
        if (avail) {
          newAvailability.set(court.id, avail);
        }
      });

      await Promise.all(promises);
      setAvailability(newAvailability);
      setLoading(false);
    },
    [fetchCourtAvailability]
  );

  // Initial load
  useEffect(() => {
    const load = async () => {
      setLoading(true);
      const courtsList = await fetchCourts();
      if (courtsList.length > 0) {
        await fetchAllAvailability(courtsList, formatDateForApi(date));
      } else {
        setLoading(false);
      }
    };
    load();
  }, [fetchCourts, fetchAllAvailability, date]);

  // Navigation functions
  const goToPrevDay = () => {
    const newDate = new Date(date);
    newDate.setDate(newDate.getDate() - 1);
    setDate(newDate);
  };

  const goToToday = () => {
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    setDate(today);
  };

  const goToNextDay = () => {
    const newDate = new Date(date);
    newDate.setDate(newDate.getDate() + 1);
    setDate(newDate);
  };

  // Handle slot click
  const handleSlotClick = (court: Court, slot: Slot) => {
    if (onSlotClick) {
      onSlotClick({
        courtId: court.id,
        courtName: court.name,
        date: formatDateForApi(date),
        time: slot.time,
        available: slot.available,
        price: slot.price,
        bookingId: slot.bookingId,
      });
    }
  };

  // Get all unique time slots across all courts
  const getAllTimeSlots = (): string[] => {
    const times = new Set<string>();
    availability.forEach((avail) => {
      avail.slots.forEach((slot) => {
        times.add(slot.time);
      });
    });
    return Array.from(times).sort();
  };

  // Check if current date is today
  const isToday = (): boolean => {
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    return date.getTime() === today.getTime();
  };

  if (error) {
    return (
      <Card>
        <CardContent className="p-6">
          <div className="text-center text-red-600">
            <p>{error}</p>
            <Button
              variant="outline"
              className="mt-4"
              onClick={() => {
                setError(null);
                fetchCourts();
              }}
            >
              Retry
            </Button>
          </div>
        </CardContent>
      </Card>
    );
  }

  const timeSlots = getAllTimeSlots();

  return (
    <Card>
      <CardHeader className="pb-4">
        <div className="flex items-center justify-between">
          <CardTitle className="text-lg">Calendar</CardTitle>
          <div className="flex items-center gap-2">
            <Button variant="outline" size="sm" onClick={goToPrevDay}>
              <svg
                className="h-4 w-4"
                fill="none"
                stroke="currentColor"
                viewBox="0 0 24 24"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M15 19l-7-7 7-7"
                />
              </svg>
            </Button>
            <Button
              variant={isToday() ? "default" : "outline"}
              size="sm"
              onClick={goToToday}
            >
              Today
            </Button>
            <Button variant="outline" size="sm" onClick={goToNextDay}>
              <svg
                className="h-4 w-4"
                fill="none"
                stroke="currentColor"
                viewBox="0 0 24 24"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M9 5l7 7-7 7"
                />
              </svg>
            </Button>
          </div>
        </div>
        <p className="text-sm text-primary-600 mt-1">{formatDate(date)}</p>
      </CardHeader>
      <CardContent className="p-0">
        {loading ? (
          <div className="flex items-center justify-center p-12">
            <div className="flex flex-col items-center gap-3">
              <div className="h-8 w-8 animate-spin rounded-full border-4 border-primary-200 border-t-primary-600" />
              <p className="text-sm text-primary-500">Loading availability...</p>
            </div>
          </div>
        ) : courts.length === 0 ? (
          <div className="p-6 text-center text-primary-500">
            <p>No courts available.</p>
          </div>
        ) : (
          <div className="overflow-x-auto">
            <div className="min-w-full">
              {/* Header with court names */}
              <div
                className={cn(
                  "grid border-b border-primary-200 bg-primary-50",
                  courts.length === 1 && "grid-cols-1",
                  courts.length === 2 && "grid-cols-2",
                  courts.length === 3 && "grid-cols-3",
                  courts.length === 4 && "grid-cols-4",
                  courts.length >= 5 && "grid-cols-5"
                )}
              >
                {courts.map((court) => (
                  <div
                    key={court.id}
                    className="border-r border-primary-200 last:border-r-0 p-4 text-center"
                  >
                    <h3 className="font-semibold text-primary-800">
                      {court.name}
                    </h3>
                    <p className="text-xs text-primary-500 mt-1">
                      {court.type === "INDOOR" ? "Indoor" : "Outdoor"}
                    </p>
                  </div>
                ))}
              </div>

              {/* Time slots grid */}
              <div className="divide-y divide-primary-100">
                {timeSlots.map((time) => (
                  <div
                    key={time}
                    className={cn(
                      "grid",
                      courts.length === 1 && "grid-cols-1",
                      courts.length === 2 && "grid-cols-2",
                      courts.length === 3 && "grid-cols-3",
                      courts.length === 4 && "grid-cols-4",
                      courts.length >= 5 && "grid-cols-5"
                    )}
                  >
                    {courts.map((court) => {
                      const courtAvail = availability.get(court.id);
                      const slot = courtAvail?.slots.find((s) => s.time === time);

                      if (!slot) {
                        return (
                          <div
                            key={court.id}
                            className="border-r border-primary-200 last:border-r-0 p-2"
                          >
                            <div className="rounded-md border border-primary-200 bg-primary-50 p-3 text-center text-xs text-primary-400">
                              Not available
                            </div>
                          </div>
                        );
                      }

                      return (
                        <div
                          key={court.id}
                          className="border-r border-primary-200 last:border-r-0 p-2"
                        >
                          <TimeSlot
                            time={slot.time}
                            available={slot.available}
                            price={slot.price}
                            clientName={slot.clientName}
                            onClick={() => handleSlotClick(court, slot)}
                          />
                        </div>
                      );
                    })}
                  </div>
                ))}

                {timeSlots.length === 0 && (
                  <div className="p-6 text-center text-primary-500">
                    <p>No time slots available for this day.</p>
                  </div>
                )}
              </div>
            </div>
          </div>
        )}
      </CardContent>
    </Card>
  );
}
