"use client";

import * as React from "react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";
import { Clock } from "lucide-react";
import { Input } from "@/components/ui/input";

export interface TimeSlot {
  time: string; // Format: "1:00 AM", "2:30 PM", etc.
  value: string; // Format: "13:00", "14:30", etc. (24-hour)
  available: boolean;
  selected?: boolean;
}

interface SlotTimePickerProps {
  selectedTime?: string; // 24-hour format "13:00"
  onTimeSelect: (time: string) => void;
  unavailableSlots?: string[]; // Array of times in 24-hour format
  interval?: number; // Minutes interval (default: 15)
  className?: string;
  placeholder?: string;
}

export function SlotTimePicker({
  selectedTime,
  onTimeSelect,
  unavailableSlots = [],
  interval = 15,
  className,
  placeholder = "Select time",
}: SlotTimePickerProps) {
  const [open, setOpen] = React.useState(false);

  // Generate all 24-hour time slots
  const generateTimeSlots = React.useMemo(() => {
    const slots: TimeSlot[] = [];
    
    for (let hour = 0; hour < 24; hour++) {
      for (let minute = 0; minute < 60; minute += interval) {
        const time24 = `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
        const displayTime = formatTime12Hour(hour, minute);
        
        slots.push({
          time: displayTime,
          value: time24,
          available: !unavailableSlots.includes(time24),
          selected: selectedTime === time24,
        });
      }
    }
    
    return slots;
  }, [interval, unavailableSlots, selectedTime]);

  // Format time to 12-hour format
  function formatTime12Hour(hour: number, minute: number): string {
    const period = hour >= 12 ? 'PM' : 'AM';
    const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
    const minuteStr = minute.toString().padStart(2, '0');
    return `${hour12}:${minuteStr} ${period}`;
  }

  // Convert 24-hour format to display format
  function formatTimeDisplay(time24: string): string {
    if (!time24) return '';
    const [hourStr, minuteStr] = time24.split(':');
    const hour = parseInt(hourStr);
    const minute = parseInt(minuteStr);
    return formatTime12Hour(hour, minute);
  }

  // Group slots by hour (4 slots per row)
  const groupedSlots = React.useMemo(() => {
    const groups: TimeSlot[][] = [];
    for (let i = 0; i < generateTimeSlots.length; i += 4) {
      groups.push(generateTimeSlots.slice(i, i + 4));
    }
    return groups;
  }, [generateTimeSlots]);

  const handleSlotClick = (slot: TimeSlot) => {
    if (slot.available) {
      onTimeSelect(slot.value);
      setOpen(false);
    }
  };

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button
          variant="outline"
          className={cn(
            "w-full justify-start text-left font-normal",
            !selectedTime && "text-muted-foreground",
            className
          )}
        >
          <Clock className="mr-2 h-4 w-4" />
          {selectedTime ? formatTimeDisplay(selectedTime) : placeholder}
        </Button>
      </PopoverTrigger>
      <PopoverContent className="w-auto p-0" align="start">
        <div className="max-h-[400px] overflow-y-auto p-3">
          <div className="space-y-2">
            {groupedSlots.map((row, rowIndex) => (
              <div key={rowIndex} className="grid grid-cols-4 gap-2">
                {row.map((slot) => (
                  <button
                    key={slot.value}
                    type="button"
                    onClick={() => handleSlotClick(slot)}
                    disabled={!slot.available}
                    className={cn(
                      "px-3 py-2 text-sm font-medium rounded-md transition-all duration-200",
                      "focus:outline-none focus:ring-2 focus:ring-offset-2",
                      // Available slot styles
                      slot.available && !slot.selected && [
                        "bg-background text-foreground border border-input",
                        "hover:bg-accent hover:text-accent-foreground",
                        "focus:ring-primary"
                      ],
                      // Selected slot styles
                      slot.selected && slot.available && [
                        "bg-primary text-primary-foreground",
                        "hover:bg-primary/90"
                      ],
                      // Unavailable slot styles
                      !slot.available && [
                        "bg-muted/50 text-muted-foreground cursor-not-allowed",
                        "opacity-50"
                      ]
                    )}
                    aria-label={`Select time ${slot.time}`}
                    aria-pressed={slot.selected}
                    aria-disabled={!slot.available}
                  >
                    {slot.time}
                  </button>
                ))}
              </div>
            ))}
          </div>
        </div>
      </PopoverContent>
    </Popover>
  );
}

// Input-style version that looks like a text field
interface TimePickerInputProps {
  selectedTime?: string; // 24-hour format "13:00"
  onTimeSelect: (time: string) => void;
  unavailableSlots?: string[]; // Array of times in 24-hour format
  interval?: number; // Minutes interval (default: 15)
  className?: string;
  placeholder?: string;
  label?: string;
  required?: boolean;
}

export function TimePickerInput({
  selectedTime,
  onTimeSelect,
  unavailableSlots = [],
  interval = 15,
  className,
  placeholder = "Select time",
  label,
  required = false,
}: TimePickerInputProps) {
  const [open, setOpen] = React.useState(false);
  const scrollContainerRef = React.useRef<HTMLDivElement>(null);

  // Generate all 24-hour time slots
  const generateTimeSlots = React.useMemo(() => {
    const slots: TimeSlot[] = [];
    
    for (let hour = 0; hour < 24; hour++) {
      for (let minute = 0; minute < 60; minute += interval) {
        const time24 = `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
        const displayTime = formatTime12Hour(hour, minute);
        
        slots.push({
          time: displayTime,
          value: time24,
          available: !unavailableSlots.includes(time24),
          selected: selectedTime === time24,
        });
      }
    }
    
    return slots;
  }, [interval, unavailableSlots, selectedTime]);

  // Format time to 12-hour format
  function formatTime12Hour(hour: number, minute: number): string {
    const period = hour >= 12 ? 'PM' : 'AM';
    const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
    const minuteStr = minute.toString().padStart(2, '0');
    return `${hour12}:${minuteStr} ${period}`;
  }

  // Convert 24-hour format to display format
  function formatTimeDisplay(time24: string): string {
    if (!time24) return '';
    const [hourStr, minuteStr] = time24.split(':');
    const hour = parseInt(hourStr);
    const minute = parseInt(minuteStr);
    return formatTime12Hour(hour, minute);
  }

  // Get current time in 24-hour format
  function getCurrentTime(): string {
    const now = new Date();
    const hours = now.getHours().toString().padStart(2, '0');
    const minutes = Math.floor(now.getMinutes() / interval) * interval;
    const roundedMinutes = minutes.toString().padStart(2, '0');
    return `${hours}:${roundedMinutes}`;
  }

  // Find the closest time slot index to scroll to
  function getScrollTargetIndex(): number {
    const targetTime = selectedTime || getCurrentTime();
    const index = generateTimeSlots.findIndex(slot => slot.value === targetTime);
    
    // If exact match found, return it
    if (index !== -1) return index;
    
    // If no match, find the closest future time
    const targetMinutes = timeToMinutes(targetTime);
    for (let i = 0; i < generateTimeSlots.length; i++) {
      const slotMinutes = timeToMinutes(generateTimeSlots[i].value);
      if (slotMinutes >= targetMinutes) {
        return i;
      }
    }
    
    // Default to current hour if nothing found
    return Math.floor(new Date().getHours() * (60 / interval));
  }

  // Convert time string to minutes since midnight
  function timeToMinutes(time: string): number {
    const [hours, minutes] = time.split(':').map(Number);
    return hours * 60 + minutes;
  }

  // Scroll to the target time when popover opens
  React.useEffect(() => {
    if (open && scrollContainerRef.current) {
      // Small delay to ensure DOM is ready
      setTimeout(() => {
        const container = scrollContainerRef.current;
        if (!container) return;

        const targetIndex = getScrollTargetIndex();
        const rowIndex = Math.floor(targetIndex / 4); // 4 slots per row
        
        // Calculate scroll position
        // Each row is approximately 28px (py-1 + text + gap)
        const rowHeight = 28;
        const containerHeight = container.clientHeight;
        const scrollTop = (rowIndex * rowHeight) - (containerHeight / 2) + (rowHeight / 2);
        
        container.scrollTo({
          top: Math.max(0, scrollTop),
          behavior: 'smooth'
        });
      }, 50);
    }
  }, [open]);

  // Group slots by hour (4 slots per row)
  const groupedSlots = React.useMemo(() => {
    const groups: TimeSlot[][] = [];
    for (let i = 0; i < generateTimeSlots.length; i += 4) {
      groups.push(generateTimeSlots.slice(i, i + 4));
    }
    return groups;
  }, [generateTimeSlots]);

  const handleSlotClick = (slot: TimeSlot) => {
    if (slot.available) {
      onTimeSelect(slot.value);
      setOpen(false);
    }
  };

  return (
    <div className={cn("space-y-2", className)}>
      {label && (
        <label className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
          {label}
          {required && <span className="text-destructive ml-1">*</span>}
        </label>
      )}
      <Popover open={open} onOpenChange={setOpen}>
        <PopoverTrigger asChild>
          <div className="relative">
            <Input
              readOnly
              value={selectedTime ? formatTimeDisplay(selectedTime) : ''}
              placeholder={placeholder}
              className="cursor-pointer pr-10"
              onClick={() => setOpen(true)}
            />
            <Clock className="absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground pointer-events-none" />
          </div>
        </PopoverTrigger>
        <PopoverContent className="w-[320px] p-0" align="start">
          <div 
            ref={scrollContainerRef}
            className="max-h-[350px] overflow-y-auto p-2"
          >
            <div className="space-y-1.5">
              {groupedSlots.map((row, rowIndex) => (
                <div key={rowIndex} className="grid grid-cols-4 gap-1.5">
                  {row.map((slot) => (
                    <button
                      key={slot.value}
                      type="button"
                      onClick={() => handleSlotClick(slot)}
                      disabled={!slot.available}
                      className={cn(
                        "px-2 py-1 text-xs font-medium rounded transition-all duration-200",
                        "focus:outline-none focus:ring-1 focus:ring-offset-1 whitespace-nowrap",
                        // Available slot styles
                        slot.available && !slot.selected && [
                          "bg-background text-foreground border border-input",
                          "hover:bg-accent hover:text-accent-foreground hover:border-accent",
                          "focus:ring-primary"
                        ],
                        // Selected slot styles
                        slot.selected && slot.available && [
                          "bg-primary text-primary-foreground border-primary",
                          "hover:bg-primary/90"
                        ],
                        // Unavailable slot styles
                        !slot.available && [
                          "bg-muted/50 text-muted-foreground/50 cursor-not-allowed border border-muted",
                          "opacity-50"
                        ]
                      )}
                      aria-label={`Select time ${slot.time}`}
                      aria-pressed={slot.selected}
                      aria-disabled={!slot.available}
                    >
                      {slot.time}
                    </button>
                  ))}
                </div>
              ))}
            </div>
          </div>
        </PopoverContent>
      </Popover>
    </div>
  );
}
