/**
 * Mawidi Demo Scheduler - Calendar View Component
 * Interactive calendar for selecting booking dates
 */

"use client";

import React, { useState, useMemo } from "react";
import type { BookingDate } from "../types/scheduler.types";

export interface CalendarViewProps {
  /** Available booking dates */
  availableDates: BookingDate[];
  /** Currently selected date */
  selectedDate: Date | null;
  /** Callback when date is selected */
  onSelectDate: (date: Date) => void;
  /** Language for labels */
  language?: "en" | "ar";
  /** Custom className for styling */
  className?: string;
  /** Language direction */
  dir?: "ltr" | "rtl";
  /** Loading state */
  loading?: boolean;
}

const calendarLabels = {
  en: {
    months: [
      "January",
      "February",
      "March",
      "April",
      "May",
      "June",
      "July",
      "August",
      "September",
      "October",
      "November",
      "December",
    ],
    weekdays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
    title: "Select a date",
    noAvailability: "No available slots",
    today: "Today",
    tomorrow: "Tomorrow",
    previousMonth: "Previous month",
    nextMonth: "Next month",
  },
  ar: {
    months: [
      "يناير",
      "فبراير",
      "مارس",
      "أبريل",
      "مايو",
      "يونيو",
      "يوليو",
      "أغسطس",
      "سبتمبر",
      "أكتوبر",
      "نوفمبر",
      "ديسمبر",
    ],
    weekdays: [
      "الأحد",
      "الاثنين",
      "الثلاثاء",
      "الأربعاء",
      "الخميس",
      "الجمعة",
      "السبت",
    ],
    title: "اختر تاريخًا",
    noAvailability: "لا توجد فترات متاحة",
    today: "اليوم",
    tomorrow: "غدًا",
    previousMonth: "الشهر السابق",
    nextMonth: "الشهر التالي",
  },
};

/**
 * CalendarView Component
 *
 * Displays an interactive calendar with available booking dates
 * Supports month navigation and date selection
 *
 * @example
 * ```tsx
 * <CalendarView
 *   availableDates={dates}
 *   selectedDate={selectedDate}
 *   onSelectDate={(date) => setSelectedDate(date)}
 *   language="en"
 * />
 * ```
 */
export default function CalendarView({
  availableDates,
  selectedDate,
  onSelectDate,
  language = "en",
  className = "",
  dir = "ltr",
  loading = false,
}: CalendarViewProps) {
  const labels = calendarLabels[language];
  const today = useMemo(() => {
    const date = new Date();
    date.setHours(0, 0, 0, 0);
    return date;
  }, []);

  // Current month being displayed
  const [currentMonth, setCurrentMonth] = useState(today);

  // Generate calendar grid for current month
  const calendarDays = useMemo(() => {
    const year = currentMonth.getFullYear();
    const month = currentMonth.getMonth();

    // First day of month
    const firstDay = new Date(year, month, 1);
    const startingDayOfWeek = firstDay.getDay();

    // Last day of month
    const lastDay = new Date(year, month + 1, 0);
    const daysInMonth = lastDay.getDate();

    // Generate days array
    const days: (Date | null)[] = [];

    // Add empty cells for days before month starts
    for (let i = 0; i < startingDayOfWeek; i++) {
      days.push(null);
    }

    // Add all days in month
    for (let day = 1; day <= daysInMonth; day++) {
      days.push(new Date(year, month, day));
    }

    return days;
  }, [currentMonth]);

  // Create lookup map for available dates
  const availabilityMap = useMemo(() => {
    const map = new Map<string, BookingDate>();
    availableDates.forEach((date) => {
      map.set(date.dateString, date);
    });
    return map;
  }, [availableDates]);

  // Check if can navigate to previous month
  const canGoPrevious = useMemo(() => {
    const previousMonth = new Date(currentMonth);
    previousMonth.setMonth(previousMonth.getMonth() - 1);
    return previousMonth >= today;
  }, [currentMonth, today]);

  // Check if can navigate to next month (6-month booking window)
  const canGoNext = useMemo(() => {
    const maxDate = new Date(today);
    maxDate.setMonth(maxDate.getMonth() + 6); // 6-month booking window
    const nextMonth = new Date(currentMonth);
    nextMonth.setMonth(nextMonth.getMonth() + 1);
    return nextMonth <= maxDate;
  }, [currentMonth, today]);

  const navigateMonth = (direction: "prev" | "next") => {
    setCurrentMonth((prev) => {
      const newDate = new Date(prev);
      newDate.setMonth(newDate.getMonth() + (direction === "next" ? 1 : -1));
      return newDate;
    });
  };

  const formatDateKey = (date: Date): string => {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, "0");
    const day = String(date.getDate()).padStart(2, "0");
    return `${year}-${month}-${day}`;
  };

  const isDayAvailable = (date: Date): boolean => {
    const key = formatDateKey(date);
    const bookingDate = availabilityMap.get(key);
    return bookingDate?.bookable || false;
  };

  const isDaySelected = (date: Date): boolean => {
    if (!selectedDate) return false;
    return formatDateKey(date) === formatDateKey(selectedDate);
  };

  const getDayLabel = (date: Date): string => {
    const key = formatDateKey(date);
    const todayKey = formatDateKey(today);
    const tomorrow = new Date(today);
    tomorrow.setDate(tomorrow.getDate() + 1);
    const tomorrowKey = formatDateKey(tomorrow);

    if (key === todayKey) return labels.today;
    if (key === tomorrowKey) return labels.tomorrow;
    return "";
  };

  return (
    <div className={`space-y-6 ${className}`} dir={dir}>
      {/* Editorial Title */}
      <h3 className="text-xl font-semibold text-[#1E293B] dark:text-white">
        {labels.title}
      </h3>

      {/* Calendar header with month navigation - Editorial style */}
      <div className="flex items-center justify-between p-4 bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700">
        <button
          onClick={() => navigateMonth("prev")}
          disabled={!canGoPrevious}
          className="
            p-2
            transition-colors duration-200
            disabled:opacity-30
            disabled:cursor-not-allowed
            hover:bg-[#10B981]/10
            text-[#1E293B] dark:text-white
          "
          aria-label={labels.previousMonth}
        >
          <svg
            className="w-5 h-5"
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth={2}
              d={dir === "rtl" ? "M9 5l7 7-7 7" : "M15 19l-7-7 7-7"}
            />
          </svg>
        </button>

        <h4 className="text-lg font-semibold text-[#1E293B] dark:text-white">
          {labels.months[currentMonth.getMonth()]}{" "}
          <span className="font-mono">{currentMonth.getFullYear()}</span>
        </h4>

        <button
          onClick={() => navigateMonth("next")}
          disabled={!canGoNext}
          className="
            p-2
            transition-colors duration-200
            disabled:opacity-30
            disabled:cursor-not-allowed
            hover:bg-[#10B981]/10
            text-[#1E293B] dark:text-white
          "
          aria-label={labels.nextMonth}
        >
          <svg
            className="w-5 h-5"
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth={2}
              d={dir === "rtl" ? "M15 19l-7-7 7-7" : "M9 5l7 7-7 7"}
            />
          </svg>
        </button>
      </div>

      {/* Weekday headers - Editorial style */}
      <div className="grid grid-cols-7 gap-px bg-slate-200 dark:bg-slate-700">
        {labels.weekdays.map((day) => (
          <div
            key={day}
            className="bg-[#FAFAFA] dark:bg-slate-800 text-xs font-medium text-[#64748B] dark:text-slate-400 py-3 text-center"
          >
            {day}
          </div>
        ))}
      </div>

      {/* Calendar grid - Editorial style */}
      {loading ? (
        <div className="flex items-center justify-center py-12">
          <div className="w-8 h-8 border-2 border-[#10B981]/30 border-t-[#10B981] rounded-full animate-spin" />
        </div>
      ) : (
        <div className="grid grid-cols-7 gap-px bg-slate-200 dark:bg-slate-700">
          {calendarDays.map((date, index) => {
            if (!date) {
              return (
                <div
                  key={`empty-${index}`}
                  className="aspect-square bg-white dark:bg-slate-900"
                />
              );
            }

            const isAvailable = isDayAvailable(date);
            const isSelected = isDaySelected(date);
            const isPast = date < today;
            const dayLabel = getDayLabel(date);
            const key = formatDateKey(date);
            const bookingDate = availabilityMap.get(key);

            return (
              <button
                key={date.toISOString()}
                onClick={() => isAvailable && onSelectDate(date)}
                disabled={!isAvailable || isPast}
                className={`
                  relative
                  aspect-square
                  p-2
                  text-sm
                  font-medium
                  transition-all
                  duration-200
                  ${
                    isSelected
                      ? "bg-[#10B981] text-white ring-2 ring-[#10B981] ring-inset"
                      : isAvailable
                        ? "bg-white dark:bg-slate-900 text-[#1E293B] dark:text-white hover:bg-[#10B981]/10 dark:hover:bg-[#10B981]/20"
                        : "bg-slate-50 dark:bg-slate-800 text-slate-300 dark:text-slate-600 cursor-not-allowed"
                  }
                `}
                aria-label={`${date.getDate()} ${labels.months[date.getMonth()]} ${date.getFullYear()}${dayLabel ? ` - ${dayLabel}` : ""}${!isAvailable ? ` - ${labels.noAvailability}` : ""}`}
              >
                <span className="block">{date.getDate()}</span>

                {/* Day label (Today/Tomorrow) */}
                {dayLabel && (
                  <span
                    className={`absolute -bottom-0.5 left-1/2 -translate-x-1/2 text-[9px] whitespace-nowrap ${isSelected ? "text-white/80" : "text-[#10B981]"}`}
                  >
                    {dayLabel}
                  </span>
                )}

                {/* Available slots indicator - square bullet style */}
                {isAvailable &&
                  bookingDate &&
                  bookingDate.availableSlots > 0 &&
                  !isSelected && (
                    <div className="absolute top-1 right-1 w-1.5 h-1.5 bg-[#10B981]" />
                  )}
              </button>
            );
          })}
        </div>
      )}

      {/* Legend - Editorial style with square bullets */}
      <div className="flex flex-wrap items-center gap-6 pt-2 text-xs">
        <div className="flex items-center gap-2">
          <div className="w-1.5 h-1.5 bg-[#10B981]" />
          <span className="text-[#64748B] dark:text-slate-400">
            {language === "ar" ? "متاح" : "Available"}
          </span>
        </div>
        <div className="flex items-center gap-2">
          <div className="w-1.5 h-1.5 bg-slate-300 dark:bg-slate-600" />
          <span className="text-[#64748B] dark:text-slate-400">
            {language === "ar" ? "غير متاح" : "Unavailable"}
          </span>
        </div>
      </div>
    </div>
  );
}
