import { Popover, PopoverButton, PopoverPanel } from '@headlessui/react';
import {
    CalendarIcon,
    ChevronLeft,
    ChevronRight,
    Clock,
    X,
} from 'lucide-react';
import React, { useEffect, useMemo, useState } from 'react';

import { cn } from '@/lib/utils';

interface DateTimePickerProps {
    value?: string;
    onChange: (value: string) => void;
    placeholder?: string;
    className?: string;
    ariaLabelledBy?: string;
    ariaDescribedBy?: string;
    ariaInvalid?: boolean;
}

export function DateTimePicker({
    value,
    onChange,
    placeholder = 'Select date & time',
    className,
    ariaLabelledBy,
    ariaDescribedBy,
    ariaInvalid = false,
}: DateTimePickerProps) {
    // Internal parsing and tracking
    const parsedDate = useMemo(() => {
        if (!value) return null;
        const d = new Date(value);
        return isNaN(d.getTime()) ? null : d;
    }, [value]);

    // Selection tracking states
    const [currentMonth, setCurrentMonth] = useState(new Date());
    const [selectedDate, setSelectedDate] = useState<Date | null>(parsedDate);

    // Sync if external value changes
    useEffect(() => {
        if (parsedDate) {
            setSelectedDate(parsedDate);
            // Only adjust view if drastically different, or just when opened? Let's keep state
        } else {
            setSelectedDate(null);
        }
    }, [parsedDate]);

    // Date Calculation Helpers
    const daysInMonth = new Date(
        currentMonth.getFullYear(),
        currentMonth.getMonth() + 1,
        0,
    ).getDate();

    const startDayOfMonth = new Date(
        currentMonth.getFullYear(),
        currentMonth.getMonth(),
        1,
    ).getDay(); // 0 = Sunday, 1 = Monday...

    const days = Array.from({ length: daysInMonth }, (_, i) => i + 1);
    const monthName = currentMonth.toLocaleString('default', {
        month: 'long',
        year: 'numeric',
    });

    const handlePrevMonth = (e: React.MouseEvent) => {
        e.preventDefault();
        setCurrentMonth(
            new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1, 1),
        );
    };

    const handleNextMonth = (e: React.MouseEvent) => {
        e.preventDefault();
        setCurrentMonth(
            new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 1),
        );
    };

    const isToday = (day: number) => {
        const today = new Date();
        return (
            today.getDate() === day &&
            today.getMonth() === currentMonth.getMonth() &&
            today.getFullYear() === currentMonth.getFullYear()
        );
    };

    const isSelected = (day: number) => {
        if (!selectedDate) return false;
        return (
            selectedDate.getDate() === day &&
            selectedDate.getMonth() === currentMonth.getMonth() &&
            selectedDate.getFullYear() === currentMonth.getFullYear()
        );
    };

    const formatDisplay = () => {
        if (!selectedDate) return placeholder;
        return selectedDate.toLocaleString('id-ID', {
            day: '2-digit',
            month: 'short',
            year: 'numeric',
            hour: '2-digit',
            minute: '2-digit',
            hour12: false,
        });
    };

    const handleDateClick = (day: number) => {
        const newDate = new Date(
            currentMonth.getFullYear(),
            currentMonth.getMonth(),
            day,
            selectedDate?.getHours() || 9, // default to 9am if not set
            selectedDate?.getMinutes() || 0,
        );
        setSelectedDate(newDate);
        commitChange(newDate);
    };

    const handleTimeChange = (
        type: 'hour' | 'minute',
        val: string | number,
    ) => {
        const base = selectedDate || new Date();
        const next = new Date(base);
        if (type === 'hour') {
            next.setHours(Number(val));
        } else {
            next.setMinutes(Number(val));
        }
        setSelectedDate(next);
        commitChange(next);
    };

    const commitChange = (d: Date) => {
        // Format to YYYY-MM-DDTHH:mm for common standards
        const year = d.getFullYear();
        const month = String(d.getMonth() + 1).padStart(2, '0');
        const date = String(d.getDate()).padStart(2, '0');
        const hours = String(d.getHours()).padStart(2, '0');
        const minutes = String(d.getMinutes()).padStart(2, '0');
        onChange(`${year}-${month}-${date}T${hours}:${minutes}`);
    };

    const handleClear = (e: React.MouseEvent) => {
        e.preventDefault();
        e.stopPropagation();
        setSelectedDate(null);
        onChange('');
    };

    // Time picker helpers
    const hours = Array.from({ length: 24 }, (_, i) => i);
    const minutes = Array.from({ length: 60 }, (_, i) => i).filter(
        (m) => m % 5 === 0,
    ); // step every 5 mins for clean ui

    const currentHour = selectedDate ? selectedDate.getHours() : 9;
    const currentMinute = selectedDate
        ? Math.floor(selectedDate.getMinutes() / 5) * 5
        : 0;

    return (
        <Popover className="relative w-full">
            <PopoverButton
                as="button"
                aria-labelledby={ariaLabelledBy}
                aria-describedby={ariaDescribedBy}
                aria-invalid={ariaInvalid || undefined}
                className={cn(
                    'flex h-11 w-full cursor-pointer items-center justify-between rounded-xl border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
                    !selectedDate && 'text-muted-foreground',
                    ariaInvalid && 'border-destructive focus:ring-destructive',
                    className,
                )}
            >
                <div className="flex items-center gap-2 truncate">
                    <CalendarIcon size={16} className="shrink-0 opacity-50" />
                    <span className="truncate font-medium">{formatDisplay()}</span>
                </div>
                {selectedDate ? (
                    <div
                        onClick={handleClear}
                        className="rounded-full p-1 opacity-50 hover:bg-muted hover:opacity-100"
                    >
                        <X size={14} />
                    </div>
                ) : (
                    <ChevronRight size={16} className="rotate-90 opacity-50" />
                )}
            </PopoverButton>

            <PopoverPanel
                transition
                className="absolute bottom-full left-0 z-100 mb-2 w-70 rounded-xl border bg-popover p-3 text-popover-foreground shadow-lg outline-hidden transition duration-200 ease-out data-closed:translate-y-1 data-closed:opacity-0"
                // Prevents Radix Dialog / Sheet from blocking clicks if there is propagation
                onPointerDown={(e) => e.stopPropagation()}
            >
                {/* Header Navigation */}
                <div className="mb-4 flex items-center justify-between">
                    <h3 className="px-1 text-sm font-semibold">{monthName}</h3>
                    <div className="flex items-center gap-1">
                        {/* Isinya hanya ikon, jadi tanpa aria-label keduanya
                            terbaca sebagai tombol tanpa nama oleh screen
                            reader — dan tidak bisa dituju oleh peran+nama. */}
                        <button
                            type="button"
                            onClick={handlePrevMonth}
                            aria-label="Previous month"
                            className="flex h-7 w-7 cursor-pointer items-center justify-center rounded-md hover:bg-accent hover:text-accent-foreground"
                        >
                            <ChevronLeft size={16} />
                        </button>
                        <button
                            type="button"
                            onClick={handleNextMonth}
                            aria-label="Next month"
                            className="flex h-7 w-7 cursor-pointer items-center justify-center rounded-md hover:bg-accent hover:text-accent-foreground"
                        >
                            <ChevronRight size={16} />
                        </button>
                    </div>
                </div>

                {/* Calendar Grid */}
                <div className="grid grid-cols-7 gap-y-1 text-center text-xs text-muted-foreground">
                    <div>Su</div>
                    <div>Mo</div>
                    <div>Tu</div>
                    <div>We</div>
                    <div>Th</div>
                    <div>Fr</div>
                    <div>Sa</div>
                </div>

                <div className="mt-2 grid grid-cols-7 gap-1">
                    {/* Empty spaces before start of month */}
                    {Array.from({ length: startDayOfMonth }).map((_, i) => (
                        <div key={`pad-${i}`} />
                    ))}

                    {/* Month Days */}
                    {days.map((day) => {
                        const selected = isSelected(day);
                        const current = isToday(day);

                        return (
                            <button
                                key={day}
                                type="button"
                                onClick={() => handleDateClick(day)}
                                className={cn(
                                    'flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg text-xs font-medium transition-colors',
                                    selected
                                        ? 'bg-primary text-primary-foreground'
                                        : 'hover:bg-accent hover:text-accent-foreground',
                                    current && !selected && 'border border-primary/50',
                                )}
                            >
                                {day}
                            </button>
                        );
                    })}
                </div>

                {/* Time Selector Section */}
                <div className="mt-4 border-t pt-3">
                    <div className="mb-2 flex items-center gap-1.5 px-1 text-xs font-medium text-muted-foreground">
                        <Clock size={14} />
                        <span>Select Time</span>
                    </div>
                    <div className="grid grid-cols-2 gap-2">
                        <div className="flex flex-col gap-1">
                            <select
                                value={currentHour}
                                onChange={(e) =>
                                    handleTimeChange('hour', e.target.value)
                                }
                                className="rounded-lg border bg-transparent px-2 py-1 text-xs font-medium outline-none hover:bg-muted"
                            >
                                {hours.map((h) => (
                                    <option key={h} value={h}>
                                        {String(h).padStart(2, '0')}
                                    </option>
                                ))}
                            </select>
                        </div>
                        <div className="flex flex-col gap-1">
                            <select
                                value={currentMinute}
                                onChange={(e) =>
                                    handleTimeChange('minute', e.target.value)
                                }
                                className="rounded-lg border bg-transparent px-2 py-1 text-xs font-medium outline-none hover:bg-muted"
                            >
                                {minutes.map((m) => (
                                    <option key={m} value={m}>
                                        {String(m).padStart(2, '0')}
                                    </option>
                                ))}
                            </select>
                        </div>
                    </div>
                </div>
            </PopoverPanel>
        </Popover>
    );
}
