"use client"

import { useMemo } from "react"
import type { CalendarEvent } from "@/lib/types"
import { getRoomColor } from "@/lib/room-theme"
import {
  addDays,
  isSameDay,
  parseDateTime,
  WEEKDAY_LABELS,
} from "@/lib/date-utils"

const HOUR_HEIGHT = 64 // px per hour

interface WeekViewProps {
  weekStart: Date
  events: CalendarEvent[]
  showRoomColors: boolean
  onEventClick: (event: CalendarEvent) => void
}

interface PositionedEvent {
  event: CalendarEvent
  start: Date
  end: Date
  top: number
  height: number
  lane: number
  lanes: number
}

// Assign overlapping events to side-by-side lanes within a single day.
function layoutDayEvents(
  events: { event: CalendarEvent; start: Date; end: Date }[],
  hoursStart: number,
): PositionedEvent[] {
  const sorted = [...events].sort((a, b) => a.start.getTime() - b.start.getTime())
  const result: PositionedEvent[] = []
  let cluster: typeof sorted = []
  let clusterEnd = 0

  const flush = () => {
    if (cluster.length === 0) return
    // Greedy lane assignment within the cluster.
    const laneEnds: number[] = []
    const withLanes = cluster.map((item) => {
      let lane = laneEnds.findIndex((end) => end <= item.start.getTime())
      if (lane === -1) {
        lane = laneEnds.length
        laneEnds.push(item.end.getTime())
      } else {
        laneEnds[lane] = item.end.getTime()
      }
      return { ...item, lane }
    })
    const lanes = laneEnds.length
    for (const item of withLanes) {
      const startHrs = item.start.getHours() + item.start.getMinutes() / 60
      const endHrs = item.end.getHours() + item.end.getMinutes() / 60
      const safeEnd = Math.max(endHrs, startHrs + 0.5)
      result.push({
        event: item.event,
        start: item.start,
        end: item.end,
        top: (startHrs - hoursStart) * HOUR_HEIGHT,
        height: (safeEnd - startHrs) * HOUR_HEIGHT,
        lane: item.lane,
        lanes,
      })
    }
    cluster = []
    clusterEnd = 0
  }

  for (const item of sorted) {
    if (cluster.length === 0 || item.start.getTime() < clusterEnd) {
      cluster.push(item)
      clusterEnd = Math.max(clusterEnd, item.end.getTime())
    } else {
      flush()
      cluster.push(item)
      clusterEnd = item.end.getTime()
    }
  }
  flush()
  return result
}

export function WeekView({ weekStart, events, showRoomColors, onEventClick }: WeekViewProps) {
  const days = useMemo(
    () => Array.from({ length: 7 }, (_, i) => addDays(weekStart, i)),
    [weekStart],
  )

  // Determine visible hour range from events (clamped to a sensible default).
  const { hoursStart, hoursEnd } = useMemo(() => {
    let min = 8
    let max = 18
    for (const e of events) {
      const s = parseDateTime(e.start_time)
      const en = parseDateTime(e.end_time)
      if (!isNaN(s.getTime())) min = Math.min(min, s.getHours())
      if (!isNaN(en.getTime())) {
        const endHr = en.getMinutes() > 0 ? en.getHours() + 1 : en.getHours()
        max = Math.max(max, endHr)
      }
    }
    return { hoursStart: Math.max(0, min), hoursEnd: Math.min(24, Math.max(max, min + 6)) }
  }, [events])

  const timeSlots = useMemo(
    () => Array.from({ length: hoursEnd - hoursStart }, (_, i) => hoursStart + i),
    [hoursStart, hoursEnd],
  )

  const positionedByDay = useMemo(() => {
    return days.map((day) => {
      const dayEvents = events
        .map((event) => ({
          event,
          start: parseDateTime(event.start_time),
          end: parseDateTime(event.end_time),
        }))
        .filter((x) => !isNaN(x.start.getTime()) && isSameDay(x.start, day))
      return layoutDayEvents(dayEvents, hoursStart)
    })
  }, [days, events, hoursStart])

  const today = new Date()
  const gridHeight = (hoursEnd - hoursStart) * HOUR_HEIGHT

  const formatHour = (h: number) => {
    if (h === 0) return "12 AM"
    if (h === 12) return "12 PM"
    return h > 12 ? `${h - 12} PM` : `${h} AM`
  }

  return (
    <div className="h-full overflow-auto rounded-xl border border-white/20 bg-white/20 shadow-xl backdrop-blur-lg">
      {/* Week Header */}
      <div className="sticky top-0 z-10 grid grid-cols-[4rem_repeat(7,1fr)] border-b border-white/20 bg-white/10 backdrop-blur-lg">
        <div className="p-2" />
        {days.map((date, i) => {
          const isToday = isSameDay(date, today)
          return (
            <div key={i} className="border-l border-white/20 p-2 text-center">
              <div className="text-xs font-medium text-white/70">{WEEKDAY_LABELS[i]}</div>
              <div
                className={`mx-auto mt-1 flex h-8 w-8 items-center justify-center text-lg font-medium text-white ${
                  isToday ? "rounded-full bg-blue-500" : ""
                }`}
              >
                {date.getDate()}
              </div>
            </div>
          )
        })}
      </div>

      {/* Time grid */}
      <div className="grid grid-cols-[4rem_repeat(7,1fr)]">
        {/* Time labels */}
        <div>
          {timeSlots.map((hour) => (
            <div
              key={hour}
              className="border-b border-white/10 pr-2 text-right text-xs text-white/70"
              style={{ height: HOUR_HEIGHT }}
            >
              {formatHour(hour)}
            </div>
          ))}
        </div>

        {/* Day columns */}
        {days.map((day, dayIndex) => (
          <div
            key={dayIndex}
            className="relative border-l border-white/20"
            style={{ height: gridHeight }}
          >
            {timeSlots.map((hour) => (
              <div
                key={hour}
                className="border-b border-white/10"
                style={{ height: HOUR_HEIGHT }}
              />
            ))}

            {positionedByDay[dayIndex].map((pe, i) => {
              const color = showRoomColors ? getRoomColor(pe.event.room_id) : { bg: "bg-blue-500" }
              const cancelled = pe.event.status === "cancelled"
              const tentative = pe.event.status === "draft" || pe.event.status === "proposed"
              const widthPct = 100 / pe.lanes
              return (
                <button
                  key={pe.event.id + "-" + i}
                  onClick={() => onEventClick(pe.event)}
                  className={`absolute overflow-hidden rounded-md p-1.5 text-left text-xs text-white shadow-md transition-all duration-150 ease-in-out hover:z-20 hover:-translate-y-0.5 hover:shadow-lg ${color.bg} ${
                    cancelled ? "opacity-50 line-through" : ""
                  } ${tentative ? "border border-dashed border-white/70" : ""}`}
                  style={{
                    top: pe.top,
                    height: pe.height,
                    left: `calc(${pe.lane * widthPct}% + 2px)`,
                    width: `calc(${widthPct}% - 4px)`,
                  }}
                >
                  <div className="truncate font-medium">{pe.event.title}</div>
                  {pe.height > 34 && (
                    <div className="mt-0.5 truncate text-[10px] opacity-80">
                      {pe.start.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}
                      {" – "}
                      {pe.end.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}
                    </div>
                  )}
                </button>
              )
            })}
          </div>
        ))}
      </div>
    </div>
  )
}
