import { useEffect, useMemo, useState, type CSSProperties, type RefObject } from 'react';
import { createPortal } from 'react-dom';

import {
  QUARTER_RANGE_LABELS,
  buildMonthWeekRows,
  isSameWeek,
  startOfDay,
  startOfWeekMonday,
  toIsoDate,
} from '../../lib/boardCalendar';

const WEEKDAY_LABELS = ['월', '화', '수', '목', '금', '토', '일'];

interface BoardCalendarPopoverProps {
  selectedQuarter: string;
  referenceWeekMonday: Date;
  weekLensActive: boolean;
  onSelectWeek: (d: Date) => void;
  onSelectQuarter: (quarterKey: string) => void;
  onReturnToCurrentQuarter: () => void;
  onClose: () => void;
  anchorRef: RefObject<HTMLElement | null>;
}

export function BoardCalendarPopover({
  selectedQuarter,
  referenceWeekMonday,
  weekLensActive,
  onSelectWeek,
  onSelectQuarter,
  onReturnToCurrentQuarter,
  onClose,
  anchorRef,
}: BoardCalendarPopoverProps) {
  const anchorMonday = startOfWeekMonday(referenceWeekMonday);
  const [viewYear, setViewYear] = useState(() => new Date().getFullYear());
  const [viewMonth, setViewMonth] = useState(() => new Date().getMonth());

  const weekRows = useMemo(
    () => buildMonthWeekRows(viewYear, viewMonth),
    [viewYear, viewMonth],
  );

  useEffect(() => {
    if (!weekLensActive) return;
    setViewYear(anchorMonday.getFullYear());
    setViewMonth(anchorMonday.getMonth());
  }, [weekLensActive, anchorMonday]);

  useEffect(() => {
    const onPointerDown = (e: MouseEvent) => {
      const anchor = anchorRef.current;
      const target = e.target as Node;
      if (anchor?.contains(target)) return;
      const popover = document.getElementById('board-calendar-popover');
      if (popover?.contains(target)) return;
      onClose();
    };
    const onKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose();
    };
    document.addEventListener('mousedown', onPointerDown);
    document.addEventListener('keydown', onKeyDown);
    return () => {
      document.removeEventListener('mousedown', onPointerDown);
      document.removeEventListener('keydown', onKeyDown);
    };
  }, [anchorRef, onClose]);

  const rect = anchorRef.current?.getBoundingClientRect();
  const style: CSSProperties = rect
    ? { top: rect.bottom + 8, right: Math.max(12, window.innerWidth - rect.right) }
    : { top: 56, right: 24 };

  const shiftMonth = (delta: number) => {
    const d = new Date(viewYear, viewMonth + delta, 1);
    setViewYear(d.getFullYear());
    setViewMonth(d.getMonth());
  };

  const today = startOfDay(new Date());
  const todayMonday = startOfWeekMonday(today);

  return createPortal(
    <div id="board-calendar-popover" className="board-calendar-popover" style={style} role="dialog" aria-label="주차 · 분기 선택">
      <div className="board-calendar-popover-head">
        <button type="button" className="board-calendar-nav" onClick={() => shiftMonth(-1)} aria-label="이전 달">‹</button>
        <span className="board-calendar-month">{viewYear}년 {viewMonth + 1}월</span>
        <button type="button" className="board-calendar-nav" onClick={() => shiftMonth(1)} aria-label="다음 달">›</button>
      </div>

      <div className="board-calendar-quarter-row">
        {([1, 2, 3, 4] as const).map((q) => {
          const key = `${viewYear}-Q${q}`;
          const selected = !weekLensActive && selectedQuarter === key;
          return (
            <button
              key={key}
              type="button"
              className={`board-calendar-quarter-chip${selected ? ' is-selected' : ''}`}
              onClick={() => onSelectQuarter(key)}
            >
              <span className="board-calendar-quarter-chip-title">{q}분기</span>
              <span className="board-calendar-quarter-chip-range">{QUARTER_RANGE_LABELS[q - 1]}</span>
            </button>
          );
        })}
      </div>

      <div className="board-calendar-grid-wrap">
        <table className="board-calendar-grid">
          <thead>
            <tr>
              <th className="board-calendar-grid-week-col">주차</th>
              {WEEKDAY_LABELS.map((label) => (
                <th key={label}>{label}</th>
              ))}
            </tr>
          </thead>
          <tbody>
            {weekRows.map((row) => {
              const weekSelected = weekLensActive && isSameWeek(anchorMonday, row.monday);
              return (
                <tr
                  key={toIsoDate(row.monday)}
                  className={weekSelected ? 'is-selected-week' : undefined}
                  onClick={() => onSelectWeek(row.monday)}
                  role="button"
                  tabIndex={0}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter' || e.key === ' ') {
                      e.preventDefault();
                      onSelectWeek(row.monday);
                    }
                  }}
                >
                  <td className="board-calendar-grid-week-col">
                    <span className="board-calendar-week-label-btn">{row.label}</span>
                  </td>
                  {row.days.map((day) => {
                    const inMonth = day.getMonth() === viewMonth;
                    const isToday = startOfDay(day).getTime() === today.getTime();
                    return (
                      <td key={toIsoDate(day)}>
                        <span
                          className={[
                            'board-calendar-day-cell',
                            !inMonth ? 'is-outside' : '',
                            isToday ? 'is-today' : '',
                          ].filter(Boolean).join(' ')}
                        >
                          {day.getDate()}
                        </span>
                      </td>
                    );
                  })}
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>

      <div className="board-calendar-foot">
        <button type="button" onClick={() => onSelectWeek(todayMonday)}>이번 주</button>
        <button type="button" onClick={onReturnToCurrentQuarter}>이번 분기</button>
      </div>
    </div>,
    document.body,
  );
}
