"use client";

import React, { useState, useEffect } from "react";
import { Button } from "@/components/ui/button";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { CalendarIcon, ChevronLeft, ChevronRight, X } from "lucide-react";
import {
  format,
  addMonths,
  subMonths,
  startOfMonth,
  endOfMonth,
  eachDayOfInterval,
  isSameMonth,
  isSameDay,
  isToday,
} from "date-fns";
import { ko } from "date-fns/locale";
import { cn } from "@/lib/utils";

interface FormDatePickerProps {
  id?: string;
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  disabled?: boolean;
  readOnly?: boolean;
  includeTime?: boolean;
}

export const FormDatePicker: React.FC<FormDatePickerProps> = ({
  id,
  value,
  onChange,
  placeholder,
  disabled = false,
  readOnly = false,
  includeTime = false,
}) => {
  const [isOpen, setIsOpen] = useState(false);
  const [currentMonth, setCurrentMonth] = useState(new Date());
  const [viewMode, setViewMode] = useState<"calendar" | "year" | "month">("calendar");
  const [yearRangeStart, setYearRangeStart] = useState(() => Math.floor(new Date().getFullYear() / 12) * 12);
  const [timeValue, setTimeValue] = useState("00:00");
  const [isTyping, setIsTyping] = useState(false);
  const [typingValue, setTypingValue] = useState("");

  const parseDate = (val: string): Date | undefined => {
    if (!val) return undefined;
    try {
      const date = new Date(val);
      if (isNaN(date.getTime())) return undefined;
      return date;
    } catch {
      return undefined;
    }
  };

  const selectedDate = parseDate(value);

  useEffect(() => {
    if (isOpen) {
      setViewMode("calendar");
      if (selectedDate) {
        setCurrentMonth(new Date(selectedDate.getFullYear(), selectedDate.getMonth(), 1));
        setYearRangeStart(Math.floor(selectedDate.getFullYear() / 12) * 12);
        if (includeTime) {
          const hours = String(selectedDate.getHours()).padStart(2, "0");
          const minutes = String(selectedDate.getMinutes()).padStart(2, "0");
          setTimeValue(`${hours}:${minutes}`);
        }
      } else {
        setCurrentMonth(new Date());
        setYearRangeStart(Math.floor(new Date().getFullYear() / 12) * 12);
        setTimeValue("00:00");
      }
    } else {
      setIsTyping(false);
      setTypingValue("");
    }
  }, [isOpen]);

  const formatDisplayValue = (): string => {
    if (!selectedDate) return "";
    if (includeTime) return format(selectedDate, "yyyy-MM-dd HH:mm", { locale: ko });
    return format(selectedDate, "yyyy-MM-dd", { locale: ko });
  };

  const buildDateStr = (date: Date, time?: string) => {
    const y = date.getFullYear();
    const m = String(date.getMonth() + 1).padStart(2, "0");
    const d = String(date.getDate()).padStart(2, "0");
    if (includeTime) return `${y}-${m}-${d}T${time || timeValue}`;
    return `${y}-${m}-${d}`;
  };

  const handleDateClick = (date: Date) => {
    onChange(buildDateStr(date));
    if (!includeTime) setIsOpen(false);
  };

  const handleTimeChange = (newTime: string) => {
    setTimeValue(newTime);
    if (selectedDate) onChange(buildDateStr(selectedDate, newTime));
  };

  const handleSetToday = () => {
    const today = new Date();
    if (includeTime) {
      const t = `${String(today.getHours()).padStart(2, "0")}:${String(today.getMinutes()).padStart(2, "0")}`;
      onChange(buildDateStr(today, t));
    } else {
      onChange(buildDateStr(today));
    }
    setIsOpen(false);
  };

  const handleClear = () => {
    onChange("");
    setIsTyping(false);
    setIsOpen(false);
  };

  const handleTriggerInput = (raw: string) => {
    setIsTyping(true);
    setTypingValue(raw);
    if (!isOpen) setIsOpen(true);
    const digitsOnly = raw.replace(/\D/g, "");
    if (digitsOnly.length === 8) {
      const y = parseInt(digitsOnly.slice(0, 4), 10);
      const m = parseInt(digitsOnly.slice(4, 6), 10) - 1;
      const d = parseInt(digitsOnly.slice(6, 8), 10);
      const date = new Date(y, m, d);
      if (date.getFullYear() === y && date.getMonth() === m && date.getDate() === d && y >= 1900 && y <= 2100) {
        onChange(buildDateStr(date));
        setCurrentMonth(new Date(y, m, 1));
        if (!includeTime) setTimeout(() => { setIsTyping(false); setIsOpen(false); }, 400);
        else setIsTyping(false);
      }
    }
  };

  const monthStart = startOfMonth(currentMonth);
  const monthEnd = endOfMonth(currentMonth);
  const days = eachDayOfInterval({ start: monthStart, end: monthEnd });
  const dayOfWeek = monthStart.getDay();
  const paddingDays = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
  const allDays = [...Array(paddingDays).fill(null), ...days];

  return (
    <Popover open={isOpen} onOpenChange={(open) => { if (!open) { setIsOpen(false); setIsTyping(false); } }}>
      <PopoverTrigger asChild>
        <div
          id={id}
          className={cn(
            "border-input bg-background flex h-10 w-full cursor-pointer items-center rounded-md border px-3",
            (disabled || readOnly) && "cursor-not-allowed opacity-50",
            !selectedDate && !isTyping && "text-muted-foreground",
          )}
          onClick={() => { if (!disabled && !readOnly) setIsOpen(true); }}
        >
          <CalendarIcon className="text-muted-foreground mr-2 h-4 w-4 shrink-0" />
          <input
            type="text"
            inputMode="numeric"
            value={isTyping ? typingValue : (formatDisplayValue() || "")}
            placeholder={placeholder || "날짜를 선택하세요"}
            disabled={disabled || readOnly}
            onChange={(e) => handleTriggerInput(e.target.value)}
            onClick={(e) => e.stopPropagation()}
            onFocus={() => { if (!disabled && !readOnly && !isOpen) setIsOpen(true); }}
            onBlur={() => { if (!isOpen) setIsTyping(false); }}
            className="h-full w-full bg-transparent text-sm font-normal outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed"
          />
          {selectedDate && !disabled && !readOnly && !isTyping && (
            <X
              className="text-muted-foreground hover:text-foreground ml-auto h-3.5 w-3.5 shrink-0 cursor-pointer"
              onClick={(e) => {
                e.stopPropagation();
                handleClear();
              }}
            />
          )}
        </div>
      </PopoverTrigger>
      <PopoverContent className="w-auto p-0" align="start" onOpenAutoFocus={(e) => e.preventDefault()}>
        <div className="p-4">
          <div className="mb-3 flex items-center gap-2">
            <Button variant="outline" size="sm" className="h-7 text-xs" onClick={handleSetToday}>
              오늘
            </Button>
            <Button variant="outline" size="sm" className="h-7 text-xs" onClick={handleClear}>
              초기화
            </Button>
          </div>

          {viewMode === "year" ? (
            <>
              <div className="mb-4 flex items-center justify-between">
                <Button variant="ghost" size="sm" className="h-8 w-8 p-0" onClick={() => setYearRangeStart(yearRangeStart - 12)}>
                  <ChevronLeft className="h-4 w-4" />
                </Button>
                <div className="text-sm font-medium">{yearRangeStart} - {yearRangeStart + 11}</div>
                <Button variant="ghost" size="sm" className="h-8 w-8 p-0" onClick={() => setYearRangeStart(yearRangeStart + 12)}>
                  <ChevronRight className="h-4 w-4" />
                </Button>
              </div>
              <div className="grid grid-cols-4 gap-2">
                {Array.from({ length: 12 }, (_, i) => yearRangeStart + i).map((year) => (
                  <Button
                    key={year}
                    variant="ghost"
                    size="sm"
                    className={cn(
                      "h-9 text-xs",
                      year === currentMonth.getFullYear() && "bg-primary text-primary-foreground hover:bg-primary",
                      year === new Date().getFullYear() && year !== currentMonth.getFullYear() && "border-primary border",
                    )}
                    onClick={() => {
                      setCurrentMonth(new Date(year, currentMonth.getMonth(), 1));
                      setViewMode("month");
                    }}
                  >
                    {year}
                  </Button>
                ))}
              </div>
            </>
          ) : viewMode === "month" ? (
            <>
              <div className="mb-4 flex items-center justify-between">
                <Button variant="ghost" size="sm" className="h-8 w-8 p-0" onClick={() => setCurrentMonth(new Date(currentMonth.getFullYear() - 1, currentMonth.getMonth(), 1))}>
                  <ChevronLeft className="h-4 w-4" />
                </Button>
                <button
                  type="button"
                  className="hover:bg-accent rounded-md px-2 py-1 text-sm font-medium transition-colors"
                  onClick={() => {
                    setYearRangeStart(Math.floor(currentMonth.getFullYear() / 12) * 12);
                    setViewMode("year");
                  }}
                >
                  {currentMonth.getFullYear()}년
                </button>
                <Button variant="ghost" size="sm" className="h-8 w-8 p-0" onClick={() => setCurrentMonth(new Date(currentMonth.getFullYear() + 1, currentMonth.getMonth(), 1))}>
                  <ChevronRight className="h-4 w-4" />
                </Button>
              </div>
              <div className="grid grid-cols-4 gap-2">
                {Array.from({ length: 12 }, (_, i) => i).map((month) => (
                  <Button
                    key={month}
                    variant="ghost"
                    size="sm"
                    className={cn(
                      "h-9 text-xs",
                      month === currentMonth.getMonth() && "bg-primary text-primary-foreground hover:bg-primary",
                      month === new Date().getMonth() && currentMonth.getFullYear() === new Date().getFullYear() && month !== currentMonth.getMonth() && "border-primary border",
                    )}
                    onClick={() => {
                      setCurrentMonth(new Date(currentMonth.getFullYear(), month, 1));
                      setViewMode("calendar");
                    }}
                  >
                    {month + 1}월
                  </Button>
                ))}
              </div>
            </>
          ) : (
            <>
              <div className="mb-4 flex items-center justify-between">
                <Button variant="ghost" size="sm" className="h-8 w-8 p-0" onClick={() => setCurrentMonth(subMonths(currentMonth, 1))}>
                  <ChevronLeft className="h-4 w-4" />
                </Button>
                <button
                  type="button"
                  className="hover:bg-accent rounded-md px-2 py-1 text-sm font-medium transition-colors"
                  onClick={() => {
                    setYearRangeStart(Math.floor(currentMonth.getFullYear() / 12) * 12);
                    setViewMode("year");
                  }}
                >
                  {format(currentMonth, "yyyy년 MM월", { locale: ko })}
                </button>
                <Button variant="ghost" size="sm" className="h-8 w-8 p-0" onClick={() => setCurrentMonth(addMonths(currentMonth, 1))}>
                  <ChevronRight className="h-4 w-4" />
                </Button>
              </div>

              <div className="mb-2 grid grid-cols-7 gap-1">
                {["월", "화", "수", "목", "금", "토", "일"].map((day) => (
                  <div key={day} className="text-muted-foreground p-2 text-center text-xs font-medium">
                    {day}
                  </div>
                ))}
              </div>

              <div className="mb-4 grid grid-cols-7 gap-1">
                {allDays.map((date, index) => {
                  if (!date) return <div key={index} className="p-2" />;

                  const isCurrentMonth = isSameMonth(date, currentMonth);
                  const isSelected = selectedDate ? isSameDay(date, selectedDate) : false;
                  const isTodayDate = isToday(date);

                  return (
                    <Button
                      key={date.toISOString()}
                      variant="ghost"
                      size="sm"
                      className={cn(
                        "h-8 w-8 p-0 text-xs",
                        !isCurrentMonth && "text-muted-foreground opacity-50",
                        isSelected && "bg-primary text-primary-foreground hover:bg-primary",
                        isTodayDate && !isSelected && "border-primary border",
                      )}
                      onClick={() => handleDateClick(date)}
                      disabled={!isCurrentMonth}
                    >
                      {format(date, "d")}
                    </Button>
                  );
                })}
              </div>
            </>
          )}

          {includeTime && viewMode === "calendar" && (
            <div className="flex items-center gap-2">
              <span className="text-muted-foreground text-xs">시간:</span>
              <input
                type="time"
                value={timeValue}
                onChange={(e) => handleTimeChange(e.target.value)}
                className="border-input h-8 rounded-md border px-2 text-xs"
              />
            </div>
          )}
        </div>
      </PopoverContent>
    </Popover>
  );
};
