/**
 * DatePicker 컴포넌트
 * 연/월/일 선택이 가능한 드롭다운 형태의 날짜 선택기
 *
 * @param {string} value - 선택된 날짜 (YYYY-MM-DD 형식)
 * @param {function} onChange - 날짜 변경 콜백
 * @param {string} placeholder - 플레이스홀더 텍스트
 * @param {boolean} showDayOfWeek - 요일 표시 여부
 * @param {number} minYear - 선택 가능한 최소 연도 (기본값: 2000)
 */
import { useState, useEffect, useRef } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { Calendar, ChevronLeft, ChevronRight, ChevronDown } from 'lucide-react';

function DatePicker({
  value,
  onChange,
  placeholder = '날짜 선택',
  showDayOfWeek = false,
  minYear = 2000,
  min,
  max,
  compact = false,
}) {
  const [isOpen, setIsOpen] = useState(false);
  const [viewMode, setViewMode] = useState('days');
  const [viewDate, setViewDate] = useState(() => {
    if (value) return new Date(value);
    return new Date();
  });
  const ref = useRef(null);

  useEffect(() => {
    const handleClickOutside = (e) => {
      if (ref.current && !ref.current.contains(e.target)) {
        setIsOpen(false);
        setViewMode('days');
      }
    };
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, []);

  // value가 변경되면 viewDate도 업데이트
  useEffect(() => {
    if (value) {
      setViewDate(new Date(value));
    }
  }, [value]);

  const year = viewDate.getFullYear();
  const month = viewDate.getMonth();

  const firstDay = new Date(year, month, 1).getDay();
  const daysInMonth = new Date(year, month + 1, 0).getDate();

  const days = [];
  for (let i = 0; i < firstDay; i++) {
    days.push(null);
  }
  for (let i = 1; i <= daysInMonth; i++) {
    days.push(i);
  }

  // 연도 범위 계산 (minYear 기준으로 12개씩 그룹)
  const groupIndex = Math.floor((year - minYear) / 12);
  const startYear = minYear + groupIndex * 12;
  const years = Array.from({ length: 12 }, (_, i) => startYear + i);
  const canGoPrevYearRange = startYear > minYear;

  const handleButtonClick = (e, callback) => {
    e.preventDefault();
    e.stopPropagation();
    callback();
  };

  const prevMonth = () => {
    const newDate = new Date(year, month - 1, 1);
    if (newDate.getFullYear() >= minYear) {
      setViewDate(newDate);
    }
  };

  const nextMonth = () => {
    setViewDate(new Date(year, month + 1, 1));
  };

  const prevYearRange = () => {
    if (canGoPrevYearRange) {
      setViewDate(new Date(startYear - 12, month, 1));
    }
  };

  const nextYearRange = () => {
    setViewDate(new Date(startYear + 12, month, 1));
  };

  const selectDate = (day) => {
    const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
    onChange(dateStr);
    setIsOpen(false);
    setViewMode('days');
  };

  const selectYear = (y) => {
    setViewDate(new Date(y, month, 1));
  };

  const selectMonth = (m) => {
    setViewDate(new Date(year, m, 1));
    setViewMode('days');
  };

  const formatDisplayDate = (dateStr) => {
    if (!dateStr) return '';
    const [y, m, d] = dateStr.split('-');
    if (showDayOfWeek) {
      const dayNames = ['일', '월', '화', '수', '목', '금', '토'];
      const date = new Date(parseInt(y), parseInt(m) - 1, parseInt(d));
      const dayOfWeek = dayNames[date.getDay()];
      return `${y}년 ${parseInt(m)}월 ${parseInt(d)}일 (${dayOfWeek})`;
    }
    return `${y}년 ${parseInt(m)}월 ${parseInt(d)}일`;
  };

  const isSelected = (day) => {
    if (!value || !day) return false;
    const [y, m, d] = value.split('-');
    return parseInt(y) === year && parseInt(m) === month + 1 && parseInt(d) === day;
  };

  const isToday = (day) => {
    if (!day) return false;
    const today = new Date();
    return today.getFullYear() === year && today.getMonth() === month && today.getDate() === day;
  };

  const isDisabledDate = (day) => {
    if (!day) return true;
    const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
    if (min && dateStr < min) return true;
    if (max && dateStr > max) return true;
    return false;
  };

  const currentYear = new Date().getFullYear();
  const currentMonth = new Date().getMonth();
  const isCurrentYear = (y) => currentYear === y;
  const isCurrentMonth = (m) => currentYear === year && currentMonth === m;

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

  // 연도 버튼 클래스
  const getYearButtonClass = (y) => {
    if (year === y) {
      return 'bg-primary text-white';
    }
    if (isCurrentYear(y)) {
      return 'text-primary font-medium hover:bg-gray-100';
    }
    return 'text-gray-700 hover:bg-gray-100';
  };

  // 월 버튼 클래스
  const getMonthButtonClass = (m) => {
    if (month === m) {
      return 'bg-primary text-white';
    }
    if (isCurrentMonth(m)) {
      return 'text-primary font-medium hover:bg-gray-100';
    }
    return 'text-gray-700 hover:bg-gray-100';
  };

  return (
    <div ref={ref} className="relative">
      <button
        type="button"
        onClick={(e) => handleButtonClick(e, () => setIsOpen(!isOpen))}
        className={`w-full border border-gray-200 bg-white flex items-center justify-between hover:border-gray-300 transition-colors focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent ${
          compact ? 'px-4 py-2 rounded-lg' : 'px-4 py-3 rounded-xl'
        }`}
      >
        <span className={`${compact ? 'text-sm' : ''} ${value ? 'text-gray-900' : 'text-gray-400'}`}>
          {value ? formatDisplayDate(value) : placeholder}
        </span>
        <Calendar size={compact ? 16 : 18} className="text-gray-400" />
      </button>

      <AnimatePresence>
        {isOpen && (
          <motion.div
            initial={{ opacity: 0, y: -10 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -10 }}
            transition={{ duration: 0.15 }}
            className="absolute z-50 mt-2 bg-white border border-gray-200 rounded-xl shadow-lg p-4 w-80"
          >
            <div className="flex items-center justify-between mb-4">
              <button
                type="button"
                onClick={(e) =>
                  handleButtonClick(e, viewMode === 'years' ? prevYearRange : prevMonth)
                }
                disabled={
                  viewMode === 'years'
                    ? !canGoPrevYearRange
                    : year === minYear && month === 0
                }
                className={`p-1.5 rounded-lg transition-colors ${
                  (viewMode === 'years' && !canGoPrevYearRange) ||
                  (viewMode !== 'years' && year === minYear && month === 0)
                    ? 'opacity-30 cursor-not-allowed'
                    : 'hover:bg-gray-100'
                }`}
              >
                <ChevronLeft size={20} className="text-gray-600" />
              </button>
              <button
                type="button"
                onClick={(e) =>
                  handleButtonClick(e, () => setViewMode(viewMode === 'days' ? 'years' : 'days'))
                }
                className="font-medium text-gray-900 hover:text-primary transition-colors flex items-center gap-1"
              >
                {viewMode === 'years'
                  ? `${years[0]} - ${years[years.length - 1]}`
                  : `${year}년 ${month + 1}월`}
                <ChevronDown
                  size={16}
                  className={`transition-transform ${viewMode !== 'days' ? 'rotate-180' : ''}`}
                />
              </button>
              <button
                type="button"
                onClick={(e) =>
                  handleButtonClick(e, viewMode === 'years' ? nextYearRange : nextMonth)
                }
                className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors"
              >
                <ChevronRight size={20} className="text-gray-600" />
              </button>
            </div>

            <AnimatePresence mode="wait">
              {viewMode === 'years' && (
                <motion.div
                  key="years"
                  initial={{ opacity: 0 }}
                  animate={{ opacity: 1 }}
                  exit={{ opacity: 0 }}
                  transition={{ duration: 0.15 }}
                >
                  <div className="text-center text-sm text-gray-500 mb-3">년도</div>
                  <div className="grid grid-cols-4 gap-2 mb-4">
                    {years.map((y) => (
                      <button
                        key={y}
                        type="button"
                        onClick={(e) => handleButtonClick(e, () => selectYear(y))}
                        className={`py-2 rounded-lg text-sm transition-colors ${getYearButtonClass(y)}`}
                      >
                        {y}
                      </button>
                    ))}
                  </div>
                  <div className="text-center text-sm text-gray-500 mb-3">월</div>
                  <div className="grid grid-cols-4 gap-2">
                    {monthNames.map((m, i) => (
                      <button
                        key={m}
                        type="button"
                        onClick={(e) => handleButtonClick(e, () => selectMonth(i))}
                        className={`py-2 rounded-lg text-sm transition-colors ${getMonthButtonClass(i)}`}
                      >
                        {m}
                      </button>
                    ))}
                  </div>
                </motion.div>
              )}

              {viewMode === 'days' && (
                <motion.div
                  key="days"
                  initial={{ opacity: 0 }}
                  animate={{ opacity: 1 }}
                  exit={{ opacity: 0 }}
                  transition={{ duration: 0.15 }}
                >
                  <div className="grid grid-cols-7 gap-1 mb-2">
                    {['일', '월', '화', '수', '목', '금', '토'].map((d, i) => (
                      <div
                        key={d}
                        className={`text-center text-xs font-medium py-1 ${
                          i === 0 ? 'text-red-400' : i === 6 ? 'text-blue-400' : 'text-gray-400'
                        }`}
                      >
                        {d}
                      </div>
                    ))}
                  </div>
                  <div className="grid grid-cols-7 gap-1">
                    {days.map((day, i) => {
                      const dayOfWeek = i % 7;
                      const disabled = isDisabledDate(day);
                      return (
                        <button
                          key={i}
                          type="button"
                          disabled={!day || disabled}
                          onClick={(e) => day && !disabled && handleButtonClick(e, () => selectDate(day))}
                          className={`aspect-square rounded-full text-sm font-medium flex items-center justify-center transition-all
                            ${!day ? '' : disabled ? 'opacity-30 cursor-not-allowed' : 'hover:bg-gray-100'}
                            ${isSelected(day) ? 'bg-primary text-white hover:bg-primary' : ''}
                            ${isToday(day) && !isSelected(day) && !disabled ? 'text-primary font-bold' : ''}
                            ${day && !isSelected(day) && !isToday(day) && !disabled && dayOfWeek === 0 ? 'text-red-500' : ''}
                            ${day && !isSelected(day) && !isToday(day) && !disabled && dayOfWeek === 6 ? 'text-blue-500' : ''}
                            ${day && !isSelected(day) && !isToday(day) && !disabled && dayOfWeek > 0 && dayOfWeek < 6 ? 'text-gray-700' : ''}
                          `}
                        >
                          {day}
                        </button>
                      );
                    })}
                  </div>
                </motion.div>
              )}
            </AnimatePresence>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
}

export default DatePicker;
