import { useState, useRef, useEffect, useMemo, useCallback } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { ChevronLeft, ChevronRight, ChevronDown } from 'lucide-react';
import { getCategoryInfo } from '@/utils';
import { MIN_YEAR, WEEKDAYS } from '@/constants';

/**
 * Mobile용 달력 컴포넌트 (팝업형)
 * @param {Date} selectedDate - 선택된 날짜
 * @param {Array} schedules - 일정 목록 (점 표시용)
 * @param {function} onSelectDate - 날짜 선택 핸들러
 * @param {boolean} hideHeader - 헤더 숨김 여부
 * @param {Date} externalViewDate - 외부에서 제어하는 viewDate
 * @param {function} onViewDateChange - viewDate 변경 콜백
 * @param {boolean} externalShowYearMonth - 외부에서 제어하는 년월 선택 모드
 * @param {function} onShowYearMonthChange - 년월 선택 모드 변경 콜백
 */
function Calendar({
  selectedDate,
  schedules = [],
  onSelectDate,
  hideHeader = false,
  externalViewDate,
  onViewDateChange,
  externalShowYearMonth,
  onShowYearMonthChange,
}) {
  const [internalViewDate, setInternalViewDate] = useState(new Date(selectedDate));

  // 외부 viewDate가 있으면 사용, 없으면 내부 상태 사용
  const viewDate = externalViewDate || internalViewDate;
  const setViewDate = (date) => {
    if (onViewDateChange) {
      onViewDateChange(date);
    } else {
      setInternalViewDate(date);
    }
  };

  // 터치 스와이프 핸들링
  const touchStartX = useRef(0);
  const touchEndX = useRef(0);

  // 날짜별 일정 목록 가져오기 (점 표시용, 최대 3개)
  const getDaySchedules = (date) => {
    const y = date.getFullYear();
    const m = String(date.getMonth() + 1).padStart(2, '0');
    const d = String(date.getDate()).padStart(2, '0');
    const dateStr = `${y}-${m}-${d}`;
    return schedules.filter((s) => s.date?.split('T')[0] === dateStr).slice(0, 3);
  };

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

  // 2017년 1월 이전으로 이동 불가
  const canGoPrevMonth = !(year === MIN_YEAR && month === 0);

  // 달력 데이터 생성 함수
  const getCalendarDays = useCallback((y, m) => {
    const firstDay = new Date(y, m, 1);
    const lastDay = new Date(y, m + 1, 0);
    const startDay = firstDay.getDay();
    const daysInMonth = lastDay.getDate();

    const days = [];

    // 이전 달 날짜
    const prevMonth = new Date(y, m, 0);
    for (let i = startDay - 1; i >= 0; i--) {
      days.push({
        day: prevMonth.getDate() - i,
        isCurrentMonth: false,
        date: new Date(y, m - 1, prevMonth.getDate() - i),
      });
    }

    // 현재 달 날짜
    for (let i = 1; i <= daysInMonth; i++) {
      days.push({
        day: i,
        isCurrentMonth: true,
        date: new Date(y, m, i),
      });
    }

    // 다음 달 날짜 (현재 줄만 채우기)
    const remaining = (7 - (days.length % 7)) % 7;
    for (let i = 1; i <= remaining; i++) {
      days.push({
        day: i,
        isCurrentMonth: false,
        date: new Date(y, m + 1, i),
      });
    }

    return days;
  }, []);

  const changeMonth = useCallback(
    (delta) => {
      if (delta < 0 && !canGoPrevMonth) return;
      const newDate = new Date(viewDate);
      newDate.setMonth(newDate.getMonth() + delta);
      setViewDate(newDate);
    },
    [viewDate, canGoPrevMonth]
  );

  const isToday = (date) => {
    const today = new Date();
    return (
      date.getDate() === today.getDate() &&
      date.getMonth() === today.getMonth() &&
      date.getFullYear() === today.getFullYear()
    );
  };

  // 선택된 날짜인지 확인
  const isSelected = (date) => {
    return (
      date.getDate() === selectedDate.getDate() &&
      date.getMonth() === selectedDate.getMonth() &&
      date.getFullYear() === selectedDate.getFullYear()
    );
  };

  // 년월 선택 모드 - 외부에서 제어 가능
  const [internalShowYearMonth, setInternalShowYearMonth] = useState(false);
  const showYearMonth =
    externalShowYearMonth !== undefined ? externalShowYearMonth : internalShowYearMonth;
  const setShowYearMonth = (value) => {
    if (onShowYearMonthChange) {
      onShowYearMonthChange(value);
    } else {
      setInternalShowYearMonth(value);
    }
  };

  const [yearRangeStart, setYearRangeStart] = useState(MIN_YEAR);
  const yearRange = Array.from({ length: 12 }, (_, i) => yearRangeStart + i);
  const canGoPrevYearRange = yearRangeStart > MIN_YEAR;

  // 배경 스크롤 막기
  useEffect(() => {
    document.body.style.overflow = 'hidden';
    return () => {
      document.body.style.overflow = '';
    };
  }, []);

  // 현재 달 캘린더 데이터
  const currentMonthDays = useMemo(() => {
    return getCalendarDays(year, month);
  }, [year, month, getCalendarDays]);

  // 터치 핸들러
  const handleTouchStart = (e) => {
    touchStartX.current = e.touches[0].clientX;
  };

  const handleTouchMove = (e) => {
    touchEndX.current = e.touches[0].clientX;
  };

  const handleTouchEnd = () => {
    const diff = touchStartX.current - touchEndX.current;
    const threshold = 50;

    if (Math.abs(diff) > threshold) {
      if (diff > 0) {
        changeMonth(1);
      } else {
        changeMonth(-1);
      }
    }
    touchStartX.current = 0;
    touchEndX.current = 0;
  };

  // 월 렌더링 컴포넌트
  const renderMonth = (days) => (
    <div onTouchStart={handleTouchStart} onTouchMove={handleTouchMove} onTouchEnd={handleTouchEnd}>
      {/* 요일 헤더 */}
      <div className="grid grid-cols-7 gap-1 mb-2">
        {WEEKDAYS.map((day, i) => (
          <div
            key={day}
            className={`text-center text-xs font-medium py-1 ${
              i === 0 ? 'text-red-400' : i === 6 ? 'text-blue-400' : 'text-gray-500'
            }`}
          >
            {day}
          </div>
        ))}
      </div>

      {/* 날짜 그리드 */}
      <div className="grid grid-cols-7 gap-1">
        {days.map((item, index) => {
          const dayOfWeek = index % 7;
          const isSunday = dayOfWeek === 0;
          const isSaturday = dayOfWeek === 6;
          const daySchedules = item.isCurrentMonth ? getDaySchedules(item.date) : [];

          return (
            <button
              key={index}
              aria-label={`${item.date.getMonth() + 1}월 ${item.day}일${isToday(item.date) ? ' (오늘)' : ''}${daySchedules.length > 0 ? `, 일정 ${daySchedules.length}개` : ''}`}
              aria-pressed={isSelected(item.date)}
              onClick={() => onSelectDate(item.date)}
              className="flex flex-col items-center py-2"
            >
              <span
                className={`w-9 h-9 flex items-center justify-center text-sm font-medium rounded-full transition-all ${
                  !item.isCurrentMonth
                    ? 'text-gray-300'
                    : isSelected(item.date)
                    ? 'bg-primary text-white font-bold shadow-lg'
                    : isToday(item.date)
                    ? 'text-primary font-bold'
                    : isSunday
                    ? 'text-red-500 hover:bg-red-50'
                    : isSaturday
                    ? 'text-blue-500 hover:bg-blue-50'
                    : 'text-gray-700 hover:bg-gray-100'
                }`}
              >
                {item.day}
              </span>
              {/* 일정 점 - 선택된 날짜에는 표시하지 않음, 최대 3개 */}
              {!isSelected(item.date) && daySchedules.length > 0 && (
                <div className="flex gap-0.5 mt-0.5 h-1.5">
                  {daySchedules.map((schedule, i) => {
                    const categoryInfo = getCategoryInfo(schedule);
                    return (
                      <div
                        key={i}
                        className="w-1 h-1 rounded-full"
                        style={{ backgroundColor: categoryInfo.color }}
                      />
                    );
                  })}
                </div>
              )}
            </button>
          );
        })}
      </div>
    </div>
  );

  return (
    <div className="p-4">
      <AnimatePresence mode="wait">
        {showYearMonth ? (
          // 년월 선택 UI
          <motion.div
            key="yearMonth"
            initial={{ opacity: 0, y: -10 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -10 }}
            transition={{ duration: 0.15 }}
          >
            {/* 년도 범위 헤더 */}
            <div className="flex items-center justify-between mb-3">
              <button
                aria-label="이전 연도 범위"
                onClick={() =>
                  canGoPrevYearRange && setYearRangeStart(Math.max(MIN_YEAR, yearRangeStart - 12))
                }
                disabled={!canGoPrevYearRange}
                className={`p-1 ${canGoPrevYearRange ? '' : 'opacity-30'}`}
              >
                <ChevronLeft size={18} aria-hidden="true" />
              </button>
              <span className="font-semibold text-sm">
                {yearRangeStart} - {yearRangeStart + 11}
              </span>
              <button aria-label="다음 연도 범위" onClick={() => setYearRangeStart(yearRangeStart + 12)} className="p-1">
                <ChevronRight size={18} aria-hidden="true" />
              </button>
            </div>

            {/* 년도 선택 */}
            <div className="text-center text-xs text-gray-400 mb-2">년도</div>
            <div className="grid grid-cols-4 gap-2 mb-4">
              {yearRange.map((y) => {
                const isCurrentYear = y === new Date().getFullYear();
                return (
                  <button
                    key={y}
                    aria-label={`${y}년 선택`}
                    aria-pressed={y === year}
                    onClick={() => {
                      const newDate = new Date(viewDate);
                      newDate.setFullYear(y);
                      setViewDate(newDate);
                    }}
                    className={`py-2 text-sm rounded-lg transition-colors ${
                      y === year
                        ? 'bg-primary text-white'
                        : isCurrentYear
                        ? 'text-primary font-semibold hover:bg-gray-100'
                        : 'text-gray-600 hover:bg-gray-100'
                    }`}
                  >
                    {y}
                  </button>
                );
              })}
            </div>

            {/* 월 선택 */}
            <div className="text-center text-xs text-gray-400 mb-2">월</div>
            <div className="grid grid-cols-4 gap-2">
              {Array.from({ length: 12 }, (_, i) => i + 1).map((m) => {
                const today = new Date();
                const isCurrentMonth = year === today.getFullYear() && m === today.getMonth() + 1;
                return (
                  <button
                    key={m}
                    aria-label={`${m}월 선택`}
                    aria-pressed={m === month + 1}
                    onClick={() => {
                      const newDate = new Date(year, m - 1, 1);
                      setViewDate(newDate);
                      setShowYearMonth(false);
                    }}
                    className={`py-2 text-sm rounded-lg transition-colors ${
                      m === month + 1
                        ? 'bg-primary text-white'
                        : isCurrentMonth
                        ? 'text-primary font-semibold hover:bg-gray-100'
                        : 'text-gray-600 hover:bg-gray-100'
                    }`}
                  >
                    {m}월
                  </button>
                );
              })}
            </div>
          </motion.div>
        ) : (
          <motion.div
            key={`calendar-${year}-${month}`}
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.15 }}
          >
            {/* 달력 헤더 - hideHeader일 때 숨김 */}
            {!hideHeader && (
              <div className="flex items-center justify-between mb-4">
                <button
                  aria-label="이전 달"
                  onClick={() => changeMonth(-1)}
                  disabled={!canGoPrevMonth}
                  className={`p-1 ${!canGoPrevMonth ? 'opacity-30' : ''}`}
                >
                  <ChevronLeft size={18} aria-hidden="true" />
                </button>
                <button
                  aria-label="년/월 선택"
                  aria-expanded={showYearMonth}
                  onClick={() => setShowYearMonth(true)}
                  className="flex items-center gap-1 font-semibold text-sm hover:text-primary transition-colors"
                >
                  {year}년 {month + 1}월
                  <ChevronDown size={16} aria-hidden="true" />
                </button>
                <button aria-label="다음 달" onClick={() => changeMonth(1)} className="p-1">
                  <ChevronRight size={18} aria-hidden="true" />
                </button>
              </div>
            )}

            {/* 달력 (터치 스와이프 지원) */}
            {renderMonth(currentMonthDays)}

            {/* 오늘 버튼 */}
            <div className="mt-3 flex justify-center">
              <button
                aria-label="오늘 날짜로 이동"
                onClick={() => onSelectDate(new Date())}
                className="text-xs text-primary font-medium px-4 py-1.5 bg-primary/10 rounded-full"
              >
                오늘
              </button>
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
}

export default Calendar;
