"use client";

import * as React from "react";
import { format, parse, isValid } from "date-fns";
import { ko } from "date-fns/locale";
import { CalendarIcon, ChevronLeft, ChevronRight } from "lucide-react";
import type { DateRange } from "react-day-picker";

import { cn } from "./utils";
import { Button } from "./button";
import { Calendar } from "./calendar";
import { Popover, PopoverContent, PopoverTrigger } from "./popover";
import { useCalendarScheduleInit } from "@/hooks/useCalendarScheduleInit";

interface DateRangePickerProps {
  /** 시작 날짜 (yyyy-MM-dd 형식) */
  startDate?: string;
  /** 종료 날짜 (yyyy-MM-dd 형식) */
  endDate?: string;
  /** 시작 날짜 변경 핸들러 */
  onStartDateChange?: (date: string) => void;
  /** 종료 날짜 변경 핸들러 */
  onEndDateChange?: (date: string) => void;
  /** 플레이스홀더 텍스트 */
  placeholder?: string;
  /** 비활성화 여부 */
  disabled?: boolean;
  /** 추가 className */
  className?: string;
  /** 트리거 버튼 크기 */
  size?: "default" | "sm" | "lg";
  /** 날짜 표시 형식 (date-fns format) */
  displayFormat?: string;
  /** 최소 선택 가능 날짜 */
  minDate?: Date;
  /** 최대 선택 가능 날짜 */
  maxDate?: Date;
  /** 팝오버 정렬 */
  align?: "start" | "center" | "end";
}

const MONTH_LABELS = [
  "1월", "2월", "3월", "4월", "5월", "6월",
  "7월", "8월", "9월", "10월", "11월", "12월",
];

function DateRangePicker({
  startDate,
  endDate,
  onStartDateChange,
  onEndDateChange,
  placeholder = "기간 선택",
  disabled = false,
  className,
  size = "default",
  displayFormat = "yyyy년 MM월 dd일",
  minDate,
  maxDate,
  align = "start",
}: DateRangePickerProps) {
  const [open, setOpen] = React.useState(false);
  const [displayMonth, setDisplayMonth] = React.useState<Date | undefined>();
  const [showMonthPicker, setShowMonthPicker] = React.useState(false);
  const [pickerYear, setPickerYear] = React.useState(new Date().getFullYear());

  // 표시 중인 연도의 공휴일/일정 데이터를 스토어에 로드
  useCalendarScheduleInit(displayMonth?.getFullYear() ?? new Date().getFullYear());

  // 내부 범위 상태 (팝오버 내 선택 중간 상태 관리)
  const [internalRange, setInternalRange] = React.useState<DateRange | undefined>();
  // 선택 단계: 'idle' → 'selecting-end' (시작일 선택 후 종료일 대기)
  const [selectPhase, setSelectPhase] = React.useState<'idle' | 'selecting-end'>('idle');

  // 문자열 → Date 변환 (외부 prop → 버튼 텍스트용)
  const parsedStart = React.useMemo(() => {
    if (!startDate) return undefined;
    const parsed = parse(startDate, "yyyy-MM-dd", new Date());
    return isValid(parsed) ? parsed : undefined;
  }, [startDate]);

  const parsedEnd = React.useMemo(() => {
    if (!endDate) return undefined;
    const parsed = parse(endDate, "yyyy-MM-dd", new Date());
    return isValid(parsed) ? parsed : undefined;
  }, [endDate]);

  // 팝오버 열릴 때 → 기존 범위 표시, idle 상태로 시작
  React.useEffect(() => {
    if (open) {
      const date = parsedStart ?? new Date();
      setDisplayMonth(date);
      setPickerYear(date.getFullYear());
      setShowMonthPicker(false);
      // 기존 범위를 내부 상태에 반영 (하이라이트 표시용)
      setInternalRange(parsedStart ? { from: parsedStart, to: parsedEnd } : undefined);
      setSelectPhase('idle');
    }
  }, [open, parsedStart, parsedEnd]);

  // 날짜 클릭 핸들러 (react-day-picker onSelect 우회, 직접 2단계 관리)
  const handleDayClick = React.useCallback(
    (day: Date) => {
      if (selectPhase === 'idle') {
        // 첫 클릭 → 시작일만 설정, 종료일 대기
        setInternalRange({ from: day, to: undefined });
        setSelectPhase('selecting-end');
      } else {
        // 두 번째 클릭 → 종료일 설정
        const from = internalRange?.from;
        if (!from) return;

        let rangeFrom = from;
        let rangeTo = day;

        // 종료일이 시작일보다 이전이면 스왑
        if (rangeTo < rangeFrom) {
          [rangeFrom, rangeTo] = [rangeTo, rangeFrom];
        }

        // 외부 상태 반영
        onStartDateChange?.(format(rangeFrom, "yyyy-MM-dd"));
        onEndDateChange?.(format(rangeTo, "yyyy-MM-dd"));

        // 내부 상태 업데이트 & 팝오버 닫기
        setInternalRange({ from: rangeFrom, to: rangeTo });
        setSelectPhase('idle');
        setOpen(false);
      }
    },
    [selectPhase, internalRange, onStartDateChange, onEndDateChange]
  );

  // react-day-picker onSelect (내부 하이라이트 업데이트용, 닫기 로직은 handleDayClick에서 처리)
  const handleSelect = React.useCallback(
    (_range: DateRange | undefined) => {
      // handleDayClick에서 모든 로직 처리, 여기서는 무시
    },
    []
  );

  // 연월 피커에서 월 선택
  const handleMonthSelect = React.useCallback(
    (month: number) => {
      setDisplayMonth(new Date(pickerYear, month, 1));
      setShowMonthPicker(false);
    },
    [pickerYear]
  );

  // 연월 텍스트 클릭 → 연월 피커 열기
  const handleCaptionClick = React.useCallback(() => {
    setPickerYear(displayMonth?.getFullYear() ?? new Date().getFullYear());
    setShowMonthPicker(true);
  }, [displayMonth]);

  // 오늘로 이동
  const handleGoToToday = React.useCallback(() => {
    const today = new Date();
    setDisplayMonth(today);
    setShowMonthPicker(false);
  }, []);

  // 표시 텍스트
  const displayText = React.useMemo(() => {
    if (!parsedStart && !parsedEnd) return placeholder;
    const startText = parsedStart
      ? format(parsedStart, displayFormat, { locale: ko })
      : "...";
    const endText = parsedEnd
      ? format(parsedEnd, displayFormat, { locale: ko })
      : "...";
    return `${startText} ~ ${endText}`;
  }, [parsedStart, parsedEnd, displayFormat, placeholder]);

  // 버튼 크기 스타일
  const sizeClasses = {
    default: "h-10 px-3",
    sm: "h-8 px-2 text-sm",
    lg: "h-12 px-4 text-base",
  };

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button
          variant="outline"
          disabled={disabled}
          className={cn(
            "w-full justify-start text-left font-normal",
            !parsedStart && "text-muted-foreground",
            sizeClasses[size],
            className
          )}
        >
          <CalendarIcon className="mr-2 h-4 w-4 shrink-0" />
          <span className="truncate">{displayText}</span>
        </Button>
      </PopoverTrigger>
      <PopoverContent
        className="w-auto p-0"
        align={align}
        onPointerDownOutside={(e) => {
          e.preventDefault();
          setOpen(false);
        }}
        onInteractOutside={(e) => {
          e.preventDefault();
          setOpen(false);
        }}
      >
        <div className="p-3">
          {showMonthPicker ? (
            /* 연월 선택 피커 */
            <div className="w-[252px]">
              {/* 연도 네비게이션 */}
              <div className="flex items-center justify-between h-10 mb-2">
                <button
                  type="button"
                  onClick={() => setPickerYear((y) => y - 1)}
                  className="h-7 w-7 flex items-center justify-center rounded-md hover:bg-accent transition-colors"
                >
                  <ChevronLeft className="h-4 w-4" />
                </button>
                <span className="text-sm font-medium">{pickerYear}년</span>
                <button
                  type="button"
                  onClick={() => setPickerYear((y) => y + 1)}
                  className="h-7 w-7 flex items-center justify-center rounded-md hover:bg-accent transition-colors"
                >
                  <ChevronRight className="h-4 w-4" />
                </button>
              </div>
              {/* 월 그리드 (4행 3열) */}
              <div className="grid grid-cols-3 gap-2">
                {MONTH_LABELS.map((label, i) => {
                  const isActive =
                    displayMonth?.getMonth() === i &&
                    displayMonth?.getFullYear() === pickerYear;
                  return (
                    <button
                      key={i}
                      type="button"
                      onClick={() => handleMonthSelect(i)}
                      className={cn(
                        "h-9 rounded-lg text-sm font-medium transition-colors",
                        "hover:bg-accent hover:text-accent-foreground",
                        isActive &&
                          "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground"
                      )}
                    >
                      {label}
                    </button>
                  );
                })}
              </div>
              {/* 오늘 버튼 */}
              <button
                type="button"
                onClick={handleGoToToday}
                className="w-full mt-2 h-8 text-sm font-medium text-primary hover:bg-accent rounded-md transition-colors"
              >
                오늘
              </button>
            </div>
          ) : (
            /* 달력 뷰 */
            <div className="relative">
              {/* 연월 텍스트 클릭 영역 (화살표 사이) */}
              <button
                type="button"
                onClick={handleCaptionClick}
                className="absolute top-0 left-8 right-8 h-10 z-20 cursor-pointer hover:bg-accent/50 rounded-md transition-colors"
              />
              <Calendar
                mode="range"
                selected={internalRange}
                onSelect={handleSelect}
                onDayClick={handleDayClick}
                disabled={(date) => {
                  if (minDate && date < minDate) return true;
                  if (maxDate && date > maxDate) return true;
                  return false;
                }}
                month={displayMonth}
                onMonthChange={setDisplayMonth}
                classNames={{
                  months: "flex flex-col relative",
                  month: "relative",
                  month_caption: "flex justify-center items-center h-10",
                  caption_label: "text-sm font-medium",
                  nav: "absolute top-0 left-1 right-1 h-10 flex items-center justify-between z-10",
                  button_previous: cn(
                    "h-7 w-7 bg-transparent p-0 hover:bg-accent hover:text-accent-foreground rounded-md flex items-center justify-center"
                  ),
                  button_next: cn(
                    "h-7 w-7 bg-transparent p-0 hover:bg-accent hover:text-accent-foreground rounded-md flex items-center justify-center"
                  ),
                  month_grid: "w-full border-collapse space-y-1",
                  weekdays: "flex",
                  weekday:
                    "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem] text-center",
                  week: "flex w-full mt-2",
                  day: "h-9 w-9 text-center text-sm p-0 relative [&:has(>.range-end)]:rounded-r-md [&:has(>.range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md",
                  day_button: cn(
                    "h-9 w-9 p-0 font-normal rounded-md hover:bg-accent hover:text-accent-foreground flex items-center justify-center"
                  ),
                  selected:
                    "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground rounded-lg",
                  today: "bg-orange-100 text-orange-600 font-bold rounded-lg",
                  outside: "text-muted-foreground/40",
                  disabled: "opacity-50 cursor-not-allowed",
                  hidden: "invisible",
                  range_start: "range-start aria-selected:bg-primary aria-selected:text-primary-foreground rounded-l-lg",
                  range_end: "range-end aria-selected:bg-primary aria-selected:text-primary-foreground rounded-r-lg",
                  range_middle: "aria-selected:bg-accent aria-selected:text-accent-foreground",
                }}
              />
              {/* 오늘 버튼 */}
              <button
                type="button"
                onClick={handleGoToToday}
                className="w-full mt-2 h-8 text-sm font-medium text-primary hover:bg-accent rounded-md transition-colors"
              >
                오늘
              </button>
            </div>
          )}
        </div>
      </PopoverContent>
    </Popover>
  );
}

export { DateRangePicker };
export type { DateRangePickerProps };
