'use client';

import { useEffect, useRef, useState } from 'react';
import { DayPicker } from '@daypicker/persian';
import '@daypicker/react/style.css';
import { CalendarDaysIcon, XMarkIcon } from '@heroicons/react/24/outline';

interface PersianDatePickerProps {
    /** Gregorian YYYY-MM-DD, or '' when empty. */
    value: string;
    /** Called with the selected Gregorian YYYY-MM-DD, or '' when cleared. */
    onChange: (value: string) => void;
    label?: string;
    placeholder?: string;
    id?: string;
}

// Parses a Gregorian "YYYY-MM-DD" into a local Date (pinned at noon to avoid
// any date shift from timezone offsets).
const parseGregorian = (value: string): Date | null => {
    const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
    if (!match) return null;
    const date = new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]), 12, 0, 0);
    return Number.isNaN(date.getTime()) ? null : date;
};

const toGregorianValue = (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}`;
};

// Renders the given Gregorian date as a Persian (Jalali) string with Persian
// digits, e.g. "۱۴۰۴/۰۵/۱۱".
const jalaliFormat = new Intl.DateTimeFormat('fa-IR-u-ca-persian', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
});

const formatJalali = (date: Date): string => jalaliFormat.format(date);

/**
 * A Persian (Jalali) date input built on @daypicker/persian.
 *
 * The calendar operates in the Jalali calendar, but the public value is a
 * Gregorian "YYYY-MM-DD" string — the same format the native <input
 * type="date"> produced — so the accounting filters keep working unchanged.
 *
 * Note: with the default dateLib (no `timeZone` prop), @daypicker/persian
 * works with plain JS `Date` objects whose native getters already return the
 * Gregorian date; the Jalali conversion happens inside the calendar library.
 * That's why we can read `getFullYear()/getMonth()/getDate()` straight off the
 * picked date.
 */
export default function PersianDatePicker({
    value,
    onChange,
    label,
    placeholder,
    id,
}: PersianDatePickerProps) {
    const [open, setOpen] = useState(false);
    const rootRef = useRef<HTMLDivElement>(null);

    const selectedDate = value ? parseGregorian(value) : null;

    // Controlled month so the popover opens on the selected month (or now).
    const [viewMonth, setViewMonth] = useState<Date>(() => selectedDate ?? new Date());

    // Close on outside click or Escape.
    useEffect(() => {
        if (!open) return;
        const handlePointerDown = (event: MouseEvent) => {
            if (rootRef.current && !rootRef.current.contains(event.target as Node)) {
                setOpen(false);
            }
        };
        const handleKeyDown = (event: KeyboardEvent) => {
            if (event.key === 'Escape') setOpen(false);
        };
        document.addEventListener('mousedown', handlePointerDown);
        document.addEventListener('keydown', handleKeyDown);
        return () => {
            document.removeEventListener('mousedown', handlePointerDown);
            document.removeEventListener('keydown', handleKeyDown);
        };
    }, [open]);

    const handleSelect = (date: Date | undefined) => {
        if (date) onChange(toGregorianValue(date));
        setOpen(false);
    };

    const handleClear = () => {
        onChange('');
        setOpen(false);
    };

    const toggle = () => {
        setViewMonth(selectedDate ?? new Date());
        setOpen((prev) => !prev);
    };

    return (
        <div ref={rootRef} className="relative">
            {label && (
                <label htmlFor={id} className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5">
                    {label}
                </label>
            )}

            <button
                type="button"
                id={id}
                onClick={toggle}
                aria-haspopup="dialog"
                aria-expanded={open}
                className={`flex w-full items-center justify-between gap-2 px-3 py-2.5 text-right text-gray-900 dark:text-gray-100 border border-gray-200 dark:border-gray-700 rounded-xl shadow-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent sm:text-sm dark:bg-gray-800/80 transition-colors ${
                    selectedDate
                        ? 'text-gray-900 dark:text-gray-100'
                        : 'text-gray-400 dark:text-gray-500'
                }`}
            >
                <span className="truncate">{selectedDate ? formatJalali(selectedDate) : placeholder || 'انتخاب تاریخ'}</span>
                {selectedDate ? (
                    <XMarkIcon
                        className="h-4 w-4 shrink-0 text-gray-400 hover:text-red-500 transition-colors"
                        onClick={(event) => {
                            event.stopPropagation();
                            handleClear();
                        }}
                        aria-label="پاک کردن تاریخ"
                    />
                ) : (
                    <CalendarDaysIcon className="h-4 w-4 shrink-0 text-gray-400" />
                )}
            </button>

            {open && (
                <div className="absolute right-0 z-50 mt-2 bg-white dark:bg-gray-900 ring-1 ring-gray-200 dark:ring-gray-800 rounded-2xl shadow-xl p-2 max-w-[calc(100vw-3rem)] overflow-x-auto">
                    <DayPicker
                        mode="single"
                        selected={selectedDate ?? undefined}
                        onSelect={handleSelect}
                        month={viewMonth}
                        onMonthChange={setViewMonth}
                    />
                </div>
            )}
        </div>
    );
}
