'use client';

import { useMemo } from 'react';
import { cn } from '@/components/ui/utils';
import { DayCell } from './DayCell';
import { ScheduleBar } from './ScheduleBar';
import { MorePopover } from './MorePopover';
import type { MonthViewProps } from './types';
import {
  getMonthDays,
  getWeekdayHeaders,
  isCurrentMonth,
  checkIsToday,
  checkIsPast,
  isSameDate,
  splitIntoWeeks,
  getEventSegmentsForWeek,
  assignGlobalEventRows,
  getEventsForDate,
  getBadgeForDate,
} from './utils';
import { getDay, format } from 'date-fns';
import { isHoliday, getHolidayName } from '@/constants/calendarEvents';

/**
 * 월간 뷰 컴포넌트
 * - 월간 그리드 레이아웃 (7xN)
 * - 요일 헤더 (일~토)
 * - 날짜 셀 렌더링
 * - 일정 바 렌더링
 * - +N 더보기 표시
 */
export function MonthView({
  currentDate,
  events,
  badges,
  selectedDate,
  maxEventsPerDay,
  weekStartsOn,
  onDateClick,
  onEventClick,
}: MonthViewProps) {
  // 요일 헤더
  const weekdayHeaders = useMemo(
    () => getWeekdayHeaders(weekStartsOn),
    [weekStartsOn]
  );

  // 월간 날짜 배열
  const monthDays = useMemo(
    () => getMonthDays(currentDate, weekStartsOn),
    [currentDate, weekStartsOn]
  );

  // 주 단위로 분할
  const weeks = useMemo(() => splitIntoWeeks(monthDays), [monthDays]);

  // 전역 row 할당 (먼저 시작한 이벤트가 종료까지 같은 행 유지)
  const globalRowAssignments = useMemo(
    () => assignGlobalEventRows(events),
    [events]
  );

  return (
    <div className="flex flex-col">
      {/* 요일 헤더 */}
      <div className="grid grid-cols-7 mb-1">
        {weekdayHeaders.map((day, index) => {
          // 일요일: weekStartsOn=0이면 index 0, weekStartsOn=1이면 index 6
          const isSunday =
            (weekStartsOn === 0 && index === 0) ||
            (weekStartsOn === 1 && index === 6);
          // 토요일: weekStartsOn=0이면 index 6, weekStartsOn=1이면 index 5
          const isSaturday =
            (weekStartsOn === 0 && index === 6) ||
            (weekStartsOn === 1 && index === 5);

          return (
            <div
              key={day}
              className={cn(
                'text-center text-xs font-semibold py-2',
                'text-muted-foreground',
                isSunday && 'text-red-400',
                isSaturday && 'text-blue-400'
              )}
            >
              {day}
            </div>
          );
        })}
      </div>

      {/* 주 단위 렌더링 */}
      <div className="flex flex-col border rounded-md overflow-hidden">
        {weeks.map((weekDays, weekIndex) => (
          <WeekRow
            key={weekIndex}
            weekDays={weekDays}
            events={events}
            badges={badges}
            currentDate={currentDate}
            selectedDate={selectedDate}
            maxEventsPerDay={maxEventsPerDay}
            weekStartsOn={weekStartsOn}
            globalRowAssignments={globalRowAssignments}
            onDateClick={onDateClick}
            onEventClick={onEventClick}
          />
        ))}
      </div>
    </div>
  );
}

interface WeekRowProps {
  weekDays: Date[];
  events: import('./types').ScheduleEvent[];
  badges: import('./types').DayBadge[];
  currentDate: Date;
  selectedDate: Date | null;
  maxEventsPerDay: number;
  weekStartsOn: 0 | 1;
  globalRowAssignments: Map<string, number>;
  onDateClick: (date: Date) => void;
  onEventClick: (event: import('./types').ScheduleEvent) => void;
}

function WeekRow({
  weekDays,
  events,
  badges,
  currentDate,
  selectedDate,
  maxEventsPerDay,
  weekStartsOn,
  globalRowAssignments,
  onDateClick,
  onEventClick,
}: WeekRowProps) {
  // 이 주에 해당하는 이벤트 세그먼트 계산
  const eventSegments = useMemo(
    () => getEventSegmentsForWeek(events, weekDays, weekStartsOn),
    [events, weekDays, weekStartsOn]
  );

  // 표시할 이벤트 수 계산 (maxEventsPerDay 초과 시 +N 표시)
  const visibleRows = maxEventsPerDay;

  // 각 날짜별 숨겨진 이벤트 수 계산
  const hiddenEventCounts = useMemo(() => {
    const counts: Map<number, number> = new Map();

    weekDays.forEach((date, colIndex) => {
      const dayEvents = getEventsForDate(events, date);
      const hidden = Math.max(0, dayEvents.length - visibleRows);
      if (hidden > 0) {
        counts.set(colIndex, hidden);
      }
    });

    return counts;
  }, [weekDays, events, visibleRows]);

  // 셀 최소 높이 계산 (이벤트 행 수에 따라) - 더 넉넉하게 확보
  const segmentRowIndices = eventSegments.map(s => globalRowAssignments.get(s.event.id) || 0);
  const maxRowIndex = Math.max(0, ...segmentRowIndices);
  const rowHeight = Math.max(120, 48 + Math.min(maxRowIndex + 1, visibleRows) * 40 + 24);

  return (
    <div
      className="relative grid grid-cols-7 border-b border-gray-200 last:border-b-0"
      style={{ minHeight: `${rowHeight}px` }}
    >
      {/* 날짜 셀들 */}
      {weekDays.map((date, colIndex) => {
        const dayOfWeek = getDay(date);
        const isSaturday = dayOfWeek === 6;
        const isSunday = dayOfWeek === 0;
        const dateStr = format(date, 'yyyy-MM-dd');
        const isHolidayDate = isHoliday(dateStr);
        const holidayName = getHolidayName(dateStr);
        const badge = getBadgeForDate(badges, date);
        const hiddenCount = hiddenEventCounts.get(colIndex) || 0;
        const dayEvents = getEventsForDate(events, date);
        const isSelected = isSameDate(selectedDate, date);

        const isToday = checkIsToday(date);
        const isPast = checkIsPast(date);
        const isCurrMonth = isCurrentMonth(date, currentDate);

        return (
          <div
            key={date.toISOString()}
            className={cn(
              'relative p-1 border-r border-gray-200 last:border-r-0',
              'flex flex-col cursor-pointer transition-colors',
              // 기본 배경
              !isCurrMonth && 'bg-muted/30',
              // 지난 일자 - 회색 배경 (현재 월, 오늘/선택 제외)
              isPast && isCurrMonth && !isToday && !isSelected && 'bg-gray-300 dark:bg-gray-700',
              // 오늘 - 셀 전체 외곽선 하이라이트
              isToday && !isSelected && 'ring-2 ring-primary ring-inset',
              // 선택된 날짜 - 셀 전체 배경색 변경
              isSelected && 'bg-primary/15'
            )}
            onClick={() => onDateClick(date)}
          >
            {/* 날짜 셀 */}
            <DayCell
              date={date}
              isCurrentMonth={isCurrMonth}
              isToday={isToday}
              isSelected={isSelected}
              isSaturday={isSaturday}
              isSunday={isSunday}
              isHoliday={isHolidayDate}
              holidayName={holidayName}
              isPast={isPast}
              badge={badge}
              onClick={onDateClick}
            />

            {/* 더보기 버튼 (하단에 배치) */}
            {hiddenCount > 0 && (
              <div className="absolute bottom-1 left-1">
                <MorePopover
                  date={date}
                  events={dayEvents}
                  hiddenCount={hiddenCount}
                  onEventClick={onEventClick}
                  onDateClick={onDateClick}
                />
              </div>
            )}
          </div>
        );
      })}

      {/* 이벤트 바들 (절대 위치) */}
      {eventSegments
        .filter((segment) => {
          const rowIndex = globalRowAssignments.get(segment.event.id) || 0;
          return rowIndex < visibleRows;
        })
        .map((segment) => {
          const rowIndex = globalRowAssignments.get(segment.event.id) || 0;

          return (
            <ScheduleBar
              key={`${segment.event.id}-${weekDays[0].toISOString()}`}
              event={segment.event}
              isStart={segment.isStart}
              isEnd={segment.isEnd}
              colSpan={segment.colSpan}
              startCol={segment.startCol}
              rowIndex={rowIndex}
              onClick={onEventClick}
            />
          );
        })}
    </div>
  );
}