'use client';

import { useEffect, useMemo, useRef, useState } from 'react';
import { AlertTriangle, CalendarDays, ChevronLeft, ChevronRight, Clock3, X } from 'lucide-react';
import { getChinaWorkdayInfo, getDateKey } from '@/lib/china-workday-calendar';

interface WorkDateTimePickerProps {
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  className?: string;
  disabled?: boolean;
  popoverAlign?: 'left' | 'right';
  defaultHour?: number;
}

const WEEKDAYS = ['一', '二', '三', '四', '五', '六', '日'];
const HOURS = Array.from({ length: 24 }, (_, index) => index);
const MINUTES = [0, 15, 30, 45];

export function WorkDateTimePicker({
  value,
  onChange,
  placeholder = '选择日期时间',
  className = '',
  disabled = false,
  popoverAlign = 'left',
  defaultHour = 9,
}: WorkDateTimePickerProps) {
  const ref = useRef<HTMLDivElement>(null);
  const [open, setOpen] = useState(false);
  const parts = parseLocalDateTime(value, defaultHour);
  const selectedDate = parts.dateKey;
  const selectedInfo = selectedDate ? getChinaWorkdayInfo(selectedDate) : null;
  const [viewDate, setViewDate] = useState(() => getInitialViewDate(value));

  useEffect(() => {
    if (!open) return;
    const handler = (event: MouseEvent) => {
      if (ref.current && !ref.current.contains(event.target as Node)) setOpen(false);
    };
    const keyHandler = (event: KeyboardEvent) => {
      if (event.key === 'Escape') setOpen(false);
    };
    document.addEventListener('mousedown', handler);
    document.addEventListener('keydown', keyHandler);
    return () => {
      document.removeEventListener('mousedown', handler);
      document.removeEventListener('keydown', keyHandler);
    };
  }, [open]);

  useEffect(() => {
    if (value) setViewDate(getInitialViewDate(value));
  }, [value]);

  const days = useMemo(() => buildCalendarDays(viewDate), [viewDate]);
  const displayText = value ? value.replace('T', ' ') : '';
  const hasRestDayWarning = Boolean(selectedInfo && !selectedInfo.isWorkday);

  const updateDate = (dateKey: string) => {
    onChange(makeLocalDateTime(dateKey, parts.hour, parts.minute));
  };

  const updateTime = (nextHour: number, nextMinute: number) => {
    const dateKey = selectedDate || getDateKey(new Date());
    onChange(makeLocalDateTime(dateKey, nextHour, nextMinute));
  };

  const clearValue = (event: React.MouseEvent) => {
    event.stopPropagation();
    onChange('');
  };

  return (
    <div ref={ref} className="relative">
      <button
        type="button"
        disabled={disabled}
        onClick={() => setOpen((current) => !current)}
        className={`flex h-9 w-full items-center gap-2 rounded-lg border border-[var(--line)] bg-[var(--bg-card)] px-3 text-left text-[13px] transition-colors hover:border-[var(--accent)] focus:border-[var(--accent)] focus:outline-none disabled:cursor-not-allowed disabled:opacity-60 ${className}`}
      >
        <CalendarDays className="h-3.5 w-3.5 shrink-0 text-[var(--ink-muted)]" />
        <span className={`min-w-0 flex-1 truncate ${displayText ? 'text-[var(--ink)]' : 'text-[var(--ink-muted)]'}`}>
          {displayText || placeholder}
        </span>
        {hasRestDayWarning && <AlertTriangle className="h-3.5 w-3.5 shrink-0 text-amber-500" />}
        {value && (
          <span
            role="button"
            aria-label="清空时间"
            onClick={clearValue}
            className="ml-1 rounded p-0.5 text-[var(--ink-muted)] hover:bg-[var(--bg-subtle)] hover:text-[var(--ink)]"
          >
            <X className="h-3 w-3" />
          </span>
        )}
      </button>

      {open && (
        <div
          className={`absolute top-full z-[80] mt-1 w-[320px] rounded-xl border border-[var(--line)] bg-[var(--bg-card)] p-3 shadow-[var(--shadow-md)] ${
            popoverAlign === 'right' ? 'right-0' : 'left-0'
          }`}
        >
          <div className="mb-3 flex items-center justify-between">
            <button
              type="button"
              onClick={() => setViewDate(addMonths(viewDate, -1))}
              className="rounded-md p-1 text-[var(--ink-muted)] hover:bg-[var(--bg-subtle)] hover:text-[var(--ink)]"
              aria-label="上个月"
            >
              <ChevronLeft className="h-4 w-4" />
            </button>
            <span className="text-[13px] font-semibold text-[var(--ink)]">
              {viewDate.getFullYear()}年{viewDate.getMonth() + 1}月
            </span>
            <button
              type="button"
              onClick={() => setViewDate(addMonths(viewDate, 1))}
              className="rounded-md p-1 text-[var(--ink-muted)] hover:bg-[var(--bg-subtle)] hover:text-[var(--ink)]"
              aria-label="下个月"
            >
              <ChevronRight className="h-4 w-4" />
            </button>
          </div>

          <div className="mb-1 grid grid-cols-7 gap-1 text-center text-[10px] font-medium text-[var(--ink-muted)]">
            {WEEKDAYS.map((day) => <span key={day}>{day}</span>)}
          </div>

          <div className="grid grid-cols-7 gap-1">
            {days.map((day) => {
              const info = getChinaWorkdayInfo(day.dateKey);
              const isSelected = day.dateKey === selectedDate;
              const isToday = day.dateKey === getDateKey(new Date());
              const tone = getDayTone(info.type, day.inMonth, isSelected);
              return (
                <button
                  type="button"
                  key={day.dateKey}
                  onClick={() => updateDate(day.dateKey)}
                  title={info.label}
                  className={`relative flex h-9 flex-col items-center justify-center rounded-lg text-[12px] transition-colors ${tone} ${isToday && !isSelected ? 'ring-1 ring-[var(--accent-ring)]' : ''}`}
                >
                  <span className="leading-none">{day.day}</span>
                  {(info.type === 'holiday' || info.type === 'makeup_workday') && (
                    <span className="mt-0.5 h-1 w-1 rounded-full bg-current opacity-70" />
                  )}
                </button>
              );
            })}
          </div>

          <div className="mt-3 flex items-center gap-2 border-t border-[var(--line)] pt-3">
            <Clock3 className="h-3.5 w-3.5 text-[var(--ink-muted)]" />
            <select
              value={parts.hour}
              onChange={(event) => updateTime(Number(event.target.value), parts.minute)}
              className="h-8 flex-1 rounded-lg border border-[var(--line)] bg-[var(--bg-card)] px-2 text-[12px] focus:border-[var(--accent)] focus:outline-none"
            >
              {HOURS.map((hour) => (
                <option key={hour} value={hour}>{String(hour).padStart(2, '0')} 时</option>
              ))}
            </select>
            <select
              value={parts.minute}
              onChange={(event) => updateTime(parts.hour, Number(event.target.value))}
              className="h-8 flex-1 rounded-lg border border-[var(--line)] bg-[var(--bg-card)] px-2 text-[12px] focus:border-[var(--accent)] focus:outline-none"
            >
              {MINUTES.map((minute) => (
                <option key={minute} value={minute}>{String(minute).padStart(2, '0')} 分</option>
              ))}
            </select>
          </div>

          {selectedInfo && (
            <div className={`mt-2 rounded-lg px-2.5 py-2 text-[11px] ${selectedInfo.isWorkday ? 'bg-[var(--bg-subtle)] text-[var(--ink-muted)]' : 'bg-amber-50 text-amber-700'}`}>
              {selectedInfo.isWorkday
                ? selectedInfo.type === 'makeup_workday' ? `${selectedInfo.label}，按工作日处理` : '所选日期为工作日'
                : `所选日期为${selectedInfo.label}，仍可保存`}
            </div>
          )}
        </div>
      )}
    </div>
  );
}

function parseLocalDateTime(value: string, defaultHour: number): { dateKey: string; hour: number; minute: number } {
  const matched = value.match(/^(\d{4}-\d{2}-\d{2})T(\d{2}):(\d{2})/);
  if (!matched) return { dateKey: '', hour: defaultHour, minute: 0 };
  return {
    dateKey: matched[1],
    hour: Number(matched[2]),
    minute: normalizeMinute(Number(matched[3])),
  };
}

function normalizeMinute(minute: number): number {
  if (MINUTES.includes(minute)) return minute;
  return MINUTES.reduce((best, current) => Math.abs(current - minute) < Math.abs(best - minute) ? current : best, 0);
}

function makeLocalDateTime(dateKey: string, hour: number, minute: number): string {
  return `${dateKey}T${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
}

function getInitialViewDate(value: string): Date {
  const dateKey = getDateKey(value || new Date());
  const [year, month] = dateKey.split('-').map(Number);
  return new Date(year, month - 1, 1);
}

function addMonths(date: Date, count: number): Date {
  return new Date(date.getFullYear(), date.getMonth() + count, 1);
}

function buildCalendarDays(viewDate: Date): Array<{ dateKey: string; day: number; inMonth: boolean }> {
  const year = viewDate.getFullYear();
  const month = viewDate.getMonth();
  const first = new Date(year, month, 1);
  const mondayOffset = (first.getDay() + 6) % 7;
  const cursor = new Date(year, month, 1 - mondayOffset);
  const days = [];

  for (let index = 0; index < 42; index += 1) {
    days.push({
      dateKey: getDateKey(cursor),
      day: cursor.getDate(),
      inMonth: cursor.getMonth() === month,
    });
    cursor.setDate(cursor.getDate() + 1);
  }

  return days;
}

function getDayTone(type: string, inMonth: boolean, selected: boolean): string {
  if (selected) return 'bg-[var(--accent)] text-white shadow-sm';
  if (!inMonth) return 'text-[var(--ink-muted)] opacity-35 hover:bg-[var(--bg-subtle)]';
  if (type === 'holiday') return 'bg-red-50 text-red-600 hover:bg-red-100';
  if (type === 'makeup_workday') return 'bg-blue-50 text-blue-600 hover:bg-blue-100';
  if (type === 'weekend') return 'text-amber-600 hover:bg-amber-50';
  return 'text-[var(--ink-soft)] hover:bg-[var(--bg-subtle)] hover:text-[var(--ink)]';
}
