import { useMemo } from 'react'
import DayColumn from './DayColumn'
import { getDeviceAccentClass } from './TestCard'

function addDays(date, n) {
  const d = new Date(date)
  d.setDate(d.getDate() + n)
  return d
}

function formatDateRange(monday) {
  const sunday = addDays(monday, 6)
  const opts = { month: 'short', day: 'numeric' }
  const startStr = monday.toLocaleDateString('en-US', opts)
  const endStr   = sunday.toLocaleDateString('en-US', {
    month: sunday.getMonth() !== monday.getMonth() ? 'short' : undefined,
    day: 'numeric',
  })
  return `${startStr} – ${endStr}`
}

function toDateKey(date) {
  return date.toISOString().slice(0, 10)
}

function getMondayOfWeek(date) {
  const d = new Date(date)
  const day = d.getDay()
  d.setDate(d.getDate() + (day === 0 ? -6 : 1 - day))
  d.setHours(0, 0, 0, 0)
  return d
}

// Returns the two shifts that form the next/active test window.
// Window = Shift 3 of day D  →  Shift 1 of day D+1
function getNextTestWindow() {
  const now  = new Date()
  const hour = now.getHours()
  const tod  = new Date(now); tod.setHours(0, 0, 0, 0)

  // midnight–1AM: still inside shift 3 that started yesterday
  if (hour < 1) {
    return { shift3Date: toDateKey(addDays(tod, -1)), shift1Date: toDateKey(tod) }
  }
  // 1AM–5PM: shift 1 finished or in daytime gap — next window starts at 5PM today
  // 5PM–midnight: currently inside shift 3 of today
  // Both cases: upcoming/active window is shift 3 today + shift 1 tomorrow
  return { shift3Date: toDateKey(tod), shift1Date: toDateKey(addDays(tod, 1)) }
}

// scheduleData: { "YYYY-MM-DD": { shift1: [...], shift2: [...], shift3: [...] }, ... }
export default function Calendar({
  scheduleData = {},
  daytimeDateKey = null,
  weekStart,
  onWeekChange,
  dualDeviceWeekendWeekEnabled = false,
  onDualDeviceWeekendWeekEnabledChange,
  windowLookup = new Map(),
  onWindowSelect,
}) {
  const DEFAULT_SHIFT_MIN_ROWS = 3
  const SLOT_CHROME_PX = 10
  const TEST_CARD_ROW_HEIGHT_PX = 22
  const TEST_CARD_ROW_GAP_PX = 2
  const DAY_HEADER_HEIGHT_PX = 48

  const today = new Date()
  today.setHours(0, 0, 0, 0)

  const activeWindow = getNextTestWindow()

  const days = Array.from({ length: 7 }, (_, i) => addDays(weekStart, i))

  // Reorder columns: Sun Mon Tue Wed Thu Fri Sat
  // weekStart is Monday, so days[0]=Mon ... days[6]=Sun → put Sunday first
  const orderedDays = [ ...days.slice(0, 7)]
  const shiftMinRows = useMemo(() => {
    const minima = {
      shift2: DEFAULT_SHIFT_MIN_ROWS,
      shift3: DEFAULT_SHIFT_MIN_ROWS,
      nextDayShift1: DEFAULT_SHIFT_MIN_ROWS,
    }

    for (const date of orderedDays) {
      const key = toDateKey(date)
      const shifts = scheduleData[key] ?? { shift1: [], shift2: [], shift3: [] }
      const nextKey = toDateKey(addDays(date, 1))
      const nextDayShift1 = scheduleData[nextKey]?.shift1 ?? []

      minima.shift2 = Math.max(minima.shift2, shifts.shift2.length || DEFAULT_SHIFT_MIN_ROWS)
      minima.shift3 = Math.max(minima.shift3, shifts.shift3.length || DEFAULT_SHIFT_MIN_ROWS)
      minima.nextDayShift1 = Math.max(minima.nextDayShift1, nextDayShift1.length || DEFAULT_SHIFT_MIN_ROWS)
    }

    return minima
  }, [orderedDays, scheduleData])
  const slotHeights = useMemo(() => {
    const calcSlotHeight = (rows) => {
      const safeRows = Math.max(DEFAULT_SHIFT_MIN_ROWS, rows || DEFAULT_SHIFT_MIN_ROWS)
      const contentHeight = (safeRows * TEST_CARD_ROW_HEIGHT_PX) + ((safeRows - 1) * TEST_CARD_ROW_GAP_PX)
      return contentHeight + SLOT_CHROME_PX
    }

    return {
      shift2: calcSlotHeight(shiftMinRows.shift2),
      shift3: calcSlotHeight(shiftMinRows.shift3),
      nextDayShift1: calcSlotHeight(shiftMinRows.nextDayShift1),
    }
  }, [shiftMinRows])
  const totalShiftHeightPx = slotHeights.shift2 + slotHeights.shift3 + slotHeights.nextDayShift1
  const deviceLegendItems = Array.from(
    new Set(
      Object.values(scheduleData)
        .flatMap((day) => [
          ...(day?.shift1 ?? []),
          ...(day?.shift2 ?? []),
          ...(day?.shift3 ?? []),
        ])
        .map((test) => test?.device)
        .filter(Boolean),
    ),
  ).sort((a, b) => String(a).localeCompare(String(b)))

  return (
    <div className="flex flex-col gap-3 h-full">
      {/* Week navigation */}
      <div className="flex items-center gap-3">
        <button
          onClick={() => onWeekChange(addDays(weekStart, -7))}
          className="p-1 text-gray-400 hover:text-white hover:bg-gray-700 rounded transition-colors"
          title="Previous week"
        >
          <svg xmlns="http://www.w3.org/2000/svg" className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
            <path strokeLinecap="round" strokeLinejoin="round" d="M15 19l-7-7 7-7" />
          </svg>
        </button>
        <span className="text-sm font-medium text-gray-300 min-w-36 text-center">
          {formatDateRange(weekStart)}
        </span>
        <button
          onClick={() => onWeekChange(addDays(weekStart, 7))}
          className="p-1 text-gray-400 hover:text-white hover:bg-gray-700 rounded transition-colors"
          title="Next week"
        >
          <svg xmlns="http://www.w3.org/2000/svg" className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
            <path strokeLinecap="round" strokeLinejoin="round" d="M9 5l7 7-7 7" />
          </svg>
        </button>
                <button
          onClick={() => onWeekChange(getMondayOfWeek(new Date()))}
          className="px-2 py-1 text-xs font-semibold text-gray-300 border border-gray-600 rounded hover:bg-gray-700 hover:text-white transition-colors"
          title="Jump to this week"
        >
          Today
        </button>
        <div className="ml-auto flex items-center gap-2 text-xs text-gray-300 select-none">
          <span>Run both devices on weekend this week</span>
          <button
            type="button"
            role="switch"
            aria-checked={dualDeviceWeekendWeekEnabled}
            onClick={() => onDualDeviceWeekendWeekEnabledChange?.(!dualDeviceWeekendWeekEnabled)}
            className={`relative inline-flex h-5 w-9 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500/70 ${
              dualDeviceWeekendWeekEnabled ? 'bg-blue-600' : 'bg-gray-600'
            }`}
            title="Toggle dual-device weekend-start scheduling for this week"
          >
            <span
              className={`pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow transform transition-transform ${
                dualDeviceWeekendWeekEnabled ? 'translate-x-4' : 'translate-x-0'
              }`}
            />
          </button>
        </div>
      </div>

      {/* 7-day grid */}
      <div className="flex gap-2 flex-1 min-h-0 overflow-hidden">
        <div className="w-10 shrink-0 text-[10px] font-semibold uppercase tracking-wider text-gray-500">
          <div style={{ height: `${DAY_HEADER_HEIGHT_PX}px` }} />
          <div className="relative" style={{ height: `${totalShiftHeightPx}px` }}>
            <span className="absolute left-0 top-0">9AM</span>
            <span className="absolute left-0" style={{ top: `${slotHeights.shift2}px` }}>5PM</span>
            <span className="absolute left-0" style={{ top: `${slotHeights.shift2 + slotHeights.shift3}px` }}>12AM</span>
            <span
              className="absolute right-2 text-[10px] font-bold uppercase tracking-[0.16em] text-gray-600"
              style={{
                top: `${slotHeights.shift2 + slotHeights.shift3 + (slotHeights.nextDayShift1 / 2)}px`,
                transform: 'translateY(-50%) rotate(180deg)',
                writingMode: 'vertical-rl',
                textOrientation: 'mixed',
              }}
            >
              Next Day
            </span>
          </div>
        </div>

        <div className="flex gap-1.5 flex-1 overflow-x-auto">
          {orderedDays.map((date) => {
            const key    = toDateKey(date)
            const shifts = scheduleData[key] ?? { shift1: [], shift2: [], shift3: [] }
            const isToday   = date.getTime() === today.getTime()
            const isWeekend  = date.getDay() === 0 || date.getDay() === 6
            // Get next day's shift1 for display
            const nextDate = addDays(date, 1)
            const nextKey = toDateKey(nextDate)
            const nextDayShift1 = scheduleData[nextKey]?.shift1 ?? []
            // Which shifts on this date are part of the active test window?
            const activeShifts = new Set()
            if (key === activeWindow.shift3Date) activeShifts.add(3)
            if (key === activeWindow.shift1Date) activeShifts.add(1)
            // Check if next day's shift1 is active
            const nextDayShift1Active = nextKey === activeWindow.shift1Date
            return (
              <DayColumn
                key={key}
                date={date}
                isToday={isToday}
                activeShifts={activeShifts}
                shifts={shifts}
                nextDayShift1={nextDayShift1}
                nextDayShift1Active={nextDayShift1Active}
                shiftMinRows={shiftMinRows}
                slotHeights={slotHeights}
                showShift2={isWeekend || (daytimeDateKey !== null && key === daytimeDateKey)}
                windowLookup={windowLookup}
                onWindowSelect={onWindowSelect}
              />
            )
          })}
        </div>
      </div>

      {/* Legend */}
      <div className="flex flex-wrap gap-x-6 gap-y-2 text-xs text-gray-400">
        <span className="flex items-center gap-1.5"><span className="w-2.5 h-2.5 rounded-sm bg-gray-500 inline-block" />Pending</span>
        <span className="flex items-center gap-1.5"><span className="w-2.5 h-2.5 rounded-sm bg-green-700 inline-block" />Completed</span>
        <span className="flex items-center gap-1.5"><span className="w-2.5 h-2.5 rounded-sm bg-red-700 inline-block" />Rerun Required</span>
        {deviceLegendItems.map((device) => (
          <span key={device} className="flex items-center gap-1.5">
            <span className={`w-2.5 h-2.5 rounded-sm inline-block ${getDeviceAccentClass(device)}`} />
            {device}
          </span>
        ))}
      </div>
    </div>
  )
}

