import { useState, useEffect, useRef, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { motion, AnimatePresence } from 'framer-motion';
import { ChevronLeft, ChevronRight, ChevronDown, Search, X, Calendar as CalendarIcon, List } from 'lucide-react';
import { useQuery, useInfiniteQuery } from '@tanstack/react-query';
import { useInView } from 'react-intersection-observer';

import {
  MobileScheduleListCard,
  MobileScheduleSearchCard,
  MobileBirthdayCard,
  fireBirthdayConfetti,
} from '@/components/schedule';
import { getSchedules, searchSchedules } from '@/api/schedules';
import { useScheduleStore } from '@/stores';
import { getTodayKST, dayjs, getCategoryInfo } from '@/utils';

const WEEKDAYS = ['일', '월', '화', '수', '목', '금', '토'];
const MONTHS = ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'];
const SEARCH_LIMIT = 20;
const MIN_YEAR = 2017;

/**
 * Mobile 스케줄 페이지
 */
function MobileSchedule() {
  const navigate = useNavigate();
  const scrollContainerRef = useRef(null);

  // 상태 관리 (zustand store)
  const {
    currentDate,
    setCurrentDate,
    selectedDate: storedSelectedDate,
    setSelectedDate: setStoredSelectedDate,
    selectedCategories,
    setSelectedCategories,
    isSearchMode,
    setIsSearchMode,
    searchInput,
    setSearchInput,
    searchTerm,
    setSearchTerm,
  } = useScheduleStore();

  const selectedDate = storedSelectedDate === undefined ? getTodayKST() : storedSelectedDate;
  const setSelectedDate = setStoredSelectedDate;

  // 로컬 상태
  const [viewMode, setViewMode] = useState('calendar'); // 'calendar' | 'list'
  const [showMonthPicker, setShowMonthPicker] = useState(false);

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

  // 월별 일정 데이터
  const { data: schedules = [], isLoading: loading } = useQuery({
    queryKey: ['schedules', year, month + 1],
    queryFn: () => getSchedules(year, month + 1),
  });

  // 검색 무한 스크롤
  const { ref: loadMoreRef, inView } = useInView({ threshold: 0, rootMargin: '100px' });

  const {
    data: searchData,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
  } = useInfiniteQuery({
    queryKey: ['scheduleSearch', searchTerm],
    queryFn: async ({ pageParam = 0 }) => {
      return searchSchedules(searchTerm, { offset: pageParam, limit: SEARCH_LIMIT });
    },
    getNextPageParam: (lastPage) => {
      if (lastPage.hasMore) {
        return lastPage.offset + lastPage.schedules.length;
      }
      return undefined;
    },
    enabled: !!searchTerm && isSearchMode,
  });

  const searchResults = useMemo(() => {
    if (!searchData?.pages) return [];
    return searchData.pages.flatMap((page) => page.schedules);
  }, [searchData]);

  // 무한 스크롤 트리거
  const prevInViewRef = useRef(false);
  useEffect(() => {
    if (inView && !prevInViewRef.current && hasNextPage && !isFetchingNextPage && isSearchMode && searchTerm) {
      fetchNextPage();
    }
    prevInViewRef.current = inView;
  }, [inView, hasNextPage, isFetchingNextPage, fetchNextPage, isSearchMode, searchTerm]);

  // 오늘 생일 폭죽
  useEffect(() => {
    if (loading || schedules.length === 0) return;
    const today = getTodayKST();
    const confettiKey = `birthday-confetti-${today}`;
    if (localStorage.getItem(confettiKey)) return;
    const hasBirthdayToday = schedules.some((s) => s.is_birthday && s.date === today);
    if (hasBirthdayToday) {
      const timer = setTimeout(() => {
        fireBirthdayConfetti();
        localStorage.setItem(confettiKey, 'true');
      }, 500);
      return () => clearTimeout(timer);
    }
  }, [schedules, loading]);

  // 달력 계산
  const getDaysInMonth = (y, m) => new Date(y, m + 1, 0).getDate();
  const getFirstDayOfMonth = (y, m) => new Date(y, m, 1).getDay();

  const daysInMonth = getDaysInMonth(year, month);
  const firstDay = getFirstDayOfMonth(year, month);

  // 일정 날짜별 맵
  const scheduleDateMap = useMemo(() => {
    const map = new Map();
    schedules.forEach((s) => {
      const dateStr = s.date;
      if (!map.has(dateStr)) {
        map.set(dateStr, []);
      }
      map.get(dateStr).push(s);
    });
    return map;
  }, [schedules]);

  // 카테고리 추출
  const categories = useMemo(() => {
    const categoryMap = new Map();
    schedules.forEach((s) => {
      if (s.category_id && !categoryMap.has(s.category_id)) {
        categoryMap.set(s.category_id, {
          id: s.category_id,
          name: s.category_name,
          color: s.category_color,
        });
      }
    });
    return Array.from(categoryMap.values());
  }, [schedules]);

  // 필터링된 스케줄
  const filteredSchedules = useMemo(() => {
    if (isSearchMode && searchTerm) {
      if (selectedCategories.length === 0) return searchResults;
      return searchResults.filter((s) => selectedCategories.includes(s.category_id));
    }

    return schedules
      .filter((s) => {
        const matchesDate = selectedDate ? s.date === selectedDate : true;
        const matchesCategory = selectedCategories.length === 0 || selectedCategories.includes(s.category_id);
        return matchesDate && matchesCategory;
      })
      .sort((a, b) => {
        // 생일 우선
        if (a.is_birthday && !b.is_birthday) return -1;
        if (!a.is_birthday && b.is_birthday) return 1;
        // 시간순
        return (a.time || '00:00:00').localeCompare(b.time || '00:00:00');
      });
  }, [schedules, selectedDate, selectedCategories, isSearchMode, searchTerm, searchResults]);

  // 날짜별 그룹화 (리스트 모드용)
  const groupedSchedules = useMemo(() => {
    if (isSearchMode && searchTerm) {
      const groups = new Map();
      searchResults.forEach((s) => {
        if (!groups.has(s.date)) {
          groups.set(s.date, []);
        }
        groups.get(s.date).push(s);
      });
      return Array.from(groups.entries()).sort((a, b) => a[0].localeCompare(b[0]));
    }

    const groups = new Map();
    schedules.forEach((s) => {
      if (selectedCategories.length > 0 && !selectedCategories.includes(s.category_id)) return;
      if (!groups.has(s.date)) {
        groups.set(s.date, []);
      }
      groups.get(s.date).push(s);
    });
    return Array.from(groups.entries()).sort((a, b) => a[0].localeCompare(b[0]));
  }, [schedules, selectedCategories, isSearchMode, searchTerm, searchResults]);

  // 월 이동
  const canGoPrevMonth = !(year === MIN_YEAR && month === 0);

  const prevMonth = () => {
    if (!canGoPrevMonth) return;
    const newDate = new Date(year, month - 1, 1);
    setCurrentDate(newDate);
  };

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

  // 날짜 선택
  const selectDate = (day) => {
    const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
    setSelectedDate(dateStr);
  };

  // 일정 클릭
  const handleScheduleClick = (schedule) => {
    if (schedule.is_birthday) {
      const scheduleYear = new Date(schedule.date).getFullYear();
      navigate(`/birthday/${encodeURIComponent(schedule.member_names)}/${scheduleYear}`);
      return;
    }
    if ([2, 3, 6].includes(schedule.category_id)) {
      navigate(`/schedule/${schedule.id}`);
      return;
    }
    if (!schedule.description && schedule.source?.url) {
      window.open(schedule.source.url, '_blank');
    } else {
      navigate(`/schedule/${schedule.id}`);
    }
  };

  // 검색 모드 종료
  const exitSearchMode = () => {
    setIsSearchMode(false);
    setSearchInput('');
    setSearchTerm('');
  };

  return (
    <div className="flex flex-col h-full bg-gray-50">
      {/* 헤더 */}
      <div className="bg-white sticky top-0 z-20">
        {isSearchMode ? (
          // 검색 모드 헤더
          <div className="flex items-center gap-2 px-4 py-3">
            <button onClick={exitSearchMode} className="p-1">
              <ChevronLeft size={24} className="text-gray-600" />
            </button>
            <div className="flex-1 relative">
              <input
                type="text"
                placeholder="일정 검색..."
                value={searchInput}
                autoFocus
                onChange={(e) => setSearchInput(e.target.value)}
                onKeyDown={(e) => {
                  if (e.key === 'Enter' && searchInput.trim()) {
                    setSearchTerm(searchInput);
                  }
                }}
                className="w-full pl-10 pr-10 py-2 bg-gray-100 rounded-full text-sm focus:outline-none focus:ring-2 focus:ring-primary/50"
              />
              <Search size={18} className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400" />
              {searchInput && (
                <button
                  onClick={() => {
                    setSearchInput('');
                    setSearchTerm('');
                  }}
                  className="absolute right-3 top-1/2 -translate-y-1/2"
                >
                  <X size={18} className="text-gray-400" />
                </button>
              )}
            </div>
          </div>
        ) : (
          // 일반 모드 헤더
          <>
            <div className="flex items-center justify-between px-4 py-3">
              <button
                onClick={() => setShowMonthPicker(!showMonthPicker)}
                className="flex items-center gap-1 text-lg font-bold"
              >
                {year}년 {month + 1}월
                <ChevronDown size={20} className={`transition-transform ${showMonthPicker ? 'rotate-180' : ''}`} />
              </button>
              <div className="flex items-center gap-2">
                <button
                  onClick={() => setIsSearchMode(true)}
                  className="p-2 hover:bg-gray-100 rounded-full"
                >
                  <Search size={20} className="text-gray-600" />
                </button>
                <button
                  onClick={() => setViewMode(viewMode === 'calendar' ? 'list' : 'calendar')}
                  className="p-2 hover:bg-gray-100 rounded-full"
                >
                  {viewMode === 'calendar' ? (
                    <List size={20} className="text-gray-600" />
                  ) : (
                    <CalendarIcon size={20} className="text-gray-600" />
                  )}
                </button>
              </div>
            </div>

            {/* 월 선택 드롭다운 */}
            <AnimatePresence>
              {showMonthPicker && (
                <motion.div
                  initial={{ height: 0, opacity: 0 }}
                  animate={{ height: 'auto', opacity: 1 }}
                  exit={{ height: 0, opacity: 0 }}
                  className="overflow-hidden border-t border-gray-100"
                >
                  <div className="p-4">
                    <div className="flex items-center justify-between mb-4">
                      <button
                        onClick={() => setCurrentDate(new Date(year - 1, month, 1))}
                        disabled={year <= MIN_YEAR}
                        className={`p-1 ${year <= MIN_YEAR ? 'opacity-30' : ''}`}
                      >
                        <ChevronLeft size={20} />
                      </button>
                      <span className="font-medium">{year}년</span>
                      <button onClick={() => setCurrentDate(new Date(year + 1, month, 1))} className="p-1">
                        <ChevronRight size={20} />
                      </button>
                    </div>
                    <div className="grid grid-cols-4 gap-2">
                      {MONTHS.map((m, i) => (
                        <button
                          key={m}
                          onClick={() => {
                            setCurrentDate(new Date(year, i, 1));
                            setShowMonthPicker(false);
                          }}
                          className={`py-2 rounded-lg text-sm ${
                            month === i ? 'bg-primary text-white' : 'hover:bg-gray-100'
                          }`}
                        >
                          {m}
                        </button>
                      ))}
                    </div>
                  </div>
                </motion.div>
              )}
            </AnimatePresence>

            {/* 달력 모드 - 달력 그리드 */}
            {viewMode === 'calendar' && (
              <div className="px-4 pb-4">
                {/* 월 네비게이션 */}
                <div className="flex items-center justify-between mb-4">
                  <button onClick={prevMonth} disabled={!canGoPrevMonth} className={`p-1 ${!canGoPrevMonth ? 'opacity-30' : ''}`}>
                    <ChevronLeft size={20} />
                  </button>
                  <span className="font-medium">{month + 1}월</span>
                  <button onClick={nextMonth} className="p-1">
                    <ChevronRight size={20} />
                  </button>
                </div>

                {/* 요일 헤더 */}
                <div className="grid grid-cols-7 mb-2">
                  {WEEKDAYS.map((day, i) => (
                    <div
                      key={day}
                      className={`text-center text-xs font-medium py-1 ${
                        i === 0 ? 'text-red-500' : i === 6 ? 'text-blue-500' : 'text-gray-500'
                      }`}
                    >
                      {day}
                    </div>
                  ))}
                </div>

                {/* 날짜 그리드 */}
                <div className="grid grid-cols-7 gap-1">
                  {/* 전달 빈 칸 */}
                  {Array.from({ length: firstDay }).map((_, i) => (
                    <div key={`empty-${i}`} className="aspect-square" />
                  ))}

                  {/* 현재 달 날짜 */}
                  {Array.from({ length: daysInMonth }).map((_, i) => {
                    const day = i + 1;
                    const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
                    const isSelected = selectedDate === dateStr;
                    const isToday = dateStr === getTodayKST();
                    const daySchedules = scheduleDateMap.get(dateStr) || [];
                    const dayOfWeek = (firstDay + i) % 7;

                    return (
                      <button
                        key={day}
                        onClick={() => selectDate(day)}
                        className={`aspect-square flex flex-col items-center justify-center rounded-lg text-sm relative
                          ${isSelected ? 'bg-primary text-white' : ''}
                          ${isToday && !isSelected ? 'text-primary font-bold' : ''}
                          ${dayOfWeek === 0 && !isSelected ? 'text-red-500' : ''}
                          ${dayOfWeek === 6 && !isSelected ? 'text-blue-500' : ''}
                        `}
                      >
                        <span>{day}</span>
                        {!isSelected && daySchedules.length > 0 && (
                          <div className="absolute bottom-1 flex gap-0.5">
                            {daySchedules.slice(0, 3).map((s, idx) => (
                              <span
                                key={idx}
                                className="w-1 h-1 rounded-full"
                                style={{ backgroundColor: s.category_color || '#4A7C59' }}
                              />
                            ))}
                          </div>
                        )}
                      </button>
                    );
                  })}
                </div>
              </div>
            )}
          </>
        )}
      </div>

      {/* 일정 목록 */}
      <div ref={scrollContainerRef} className="flex-1 overflow-y-auto">
        {loading ? (
          <div className="flex items-center justify-center py-20">
            <div className="w-8 h-8 border-2 border-primary border-t-transparent rounded-full animate-spin" />
          </div>
        ) : isSearchMode && searchTerm ? (
          // 검색 결과
          <div className="p-4 space-y-3">
            {searchResults.length > 0 ? (
              <>
                {searchResults.map((schedule) => (
                  <div key={schedule.id}>
                    {schedule.is_birthday ? (
                      <MobileBirthdayCard schedule={schedule} showYear onClick={() => handleScheduleClick(schedule)} />
                    ) : (
                      <MobileScheduleSearchCard schedule={schedule} onClick={() => handleScheduleClick(schedule)} />
                    )}
                  </div>
                ))}
                <div ref={loadMoreRef} className="py-4">
                  {isFetchingNextPage && (
                    <div className="flex justify-center">
                      <div className="w-6 h-6 border-2 border-primary border-t-transparent rounded-full animate-spin" />
                    </div>
                  )}
                </div>
              </>
            ) : (
              <div className="text-center py-20 text-gray-400">검색 결과가 없습니다</div>
            )}
          </div>
        ) : viewMode === 'calendar' ? (
          // 달력 모드 - 선택된 날짜의 일정
          <div className="p-4 space-y-3">
            {filteredSchedules.length > 0 ? (
              filteredSchedules.map((schedule) => (
                <div key={schedule.id}>
                  {schedule.is_birthday ? (
                    <MobileBirthdayCard schedule={schedule} onClick={() => handleScheduleClick(schedule)} />
                  ) : (
                    <MobileScheduleListCard schedule={schedule} onClick={() => handleScheduleClick(schedule)} />
                  )}
                </div>
              ))
            ) : (
              <div className="text-center py-20 text-gray-400">
                {selectedDate ? '이 날짜에 일정이 없습니다' : '이번 달에 일정이 없습니다'}
              </div>
            )}
          </div>
        ) : (
          // 리스트 모드 - 날짜별 그룹화
          <div className="divide-y divide-gray-100">
            {groupedSchedules.length > 0 ? (
              groupedSchedules.map(([date, daySchedules]) => {
                const d = dayjs(date);
                return (
                  <div key={date} className="bg-white">
                    <div className="sticky top-0 bg-gray-50 px-4 py-2 text-sm font-medium text-gray-600">
                      {d.format('M월 D일')} ({WEEKDAYS[d.day()]})
                    </div>
                    <div className="p-4 space-y-3">
                      {daySchedules.map((schedule) => (
                        <div key={schedule.id}>
                          {schedule.is_birthday ? (
                            <MobileBirthdayCard schedule={schedule} onClick={() => handleScheduleClick(schedule)} />
                          ) : (
                            <MobileScheduleListCard schedule={schedule} onClick={() => handleScheduleClick(schedule)} />
                          )}
                        </div>
                      ))}
                    </div>
                  </div>
                );
              })
            ) : (
              <div className="text-center py-20 text-gray-400">이번 달에 일정이 없습니다</div>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

export default MobileSchedule;
