import {
  startOfWeek,
  addDays,
  format,
  isSameDay,
  isToday,
  parseISO,
  differenceInMinutes,
  startOfDay,
} from "date-fns";
import type { CalendarEvent, Calendar } from "../types";
import { eventStart, eventEnd } from "../types";

interface WeekViewProps {
  currentDate: Date;
  events: CalendarEvent[];
  calendars: Calendar[];
  visibleCalendarIds: Set<string>;
  onTimeClick: (date: Date) => void;
  onEventClick: (event: CalendarEvent) => void;
}

const HOURS = Array.from({ length: 24 }, (_, i) => i);
const HOUR_HEIGHT = 60;

export default function WeekView({
  currentDate,
  events,
  calendars,
  visibleCalendarIds,
  onTimeClick,
  onEventClick,
}: WeekViewProps) {
  const weekStart = startOfWeek(currentDate);
  const weekDays = Array.from({ length: 7 }, (_, i) => addDays(weekStart, i));
  const calColorMap = new Map(calendars.map((c) => [c.id, c.color]));
  const filtered = events.filter((e) => visibleCalendarIds.has(e.calendar_id));

  const allDayEvents = filtered.filter((e) => e.all_day);
  const timedEvents = filtered.filter((e) => !e.all_day);

  const getEventsForDay = (day: Date) =>
    timedEvents.filter((e) => isSameDay(parseISO(eventStart(e)), day));

  const getAllDayForDay = (day: Date) =>
    allDayEvents.filter((e) => {
      const start = parseISO(eventStart(e));
      const end = parseISO(eventEnd(e));
      return isSameDay(start, day) || isSameDay(end, day) || (start < day && end > day);
    });

  const getEventStyle = (evt: CalendarEvent) => {
    const start = parseISO(eventStart(evt));
    const dayStart = startOfDay(start);
    const top = differenceInMinutes(start, dayStart);
    const end = parseISO(eventEnd(evt));
    const duration = Math.max(differenceInMinutes(end, start), 15);
    return {
      top: `${top}px`,
      height: `${duration}px`,
      minHeight: "20px",
    };
  };

  return (
    <div className="flex flex-col h-full overflow-hidden">
      {/* Header */}
      <div className="flex border-b border-gray-200 dark:border-gray-700 flex-shrink-0">
        <div className="w-16 flex-shrink-0" />
        {weekDays.map((day) => {
          const today = isToday(day);
          return (
            <div
              key={day.toISOString()}
              className="flex-1 text-center py-2 border-l border-gray-100 dark:border-gray-700/50"
            >
              <div className="text-[10px] font-semibold text-gray-500 dark:text-gray-400 uppercase">
                {format(day, "EEE")}
              </div>
              <div
                className={`text-lg font-semibold mt-0.5 ${
                  today
                    ? "bg-blue-600 text-white w-8 h-8 rounded-full flex items-center justify-center mx-auto"
                    : "text-gray-700 dark:text-gray-300"
                }`}
              >
                {format(day, "d")}
              </div>
            </div>
          );
        })}
      </div>

      {/* All-day section */}
      {allDayEvents.length > 0 && (
        <div className="flex border-b border-gray-200 dark:border-gray-700 flex-shrink-0">
          <div className="w-16 flex-shrink-0 text-[10px] text-gray-400 dark:text-gray-500 text-right pr-2 py-1">
            all-day
          </div>
          {weekDays.map((day) => (
            <div
              key={day.toISOString()}
              className="flex-1 border-l border-gray-100 dark:border-gray-700/50 p-0.5 space-y-0.5"
            >
              {getAllDayForDay(day).map((evt) => (
                <button
                  key={evt.id}
                  onClick={() => onEventClick(evt)}
                  className="w-full text-left text-[10px] px-1.5 py-0.5 rounded text-white font-medium truncate hover:opacity-80"
                  style={{ backgroundColor: calColorMap.get(evt.calendar_id) || "#3B82F6" }}
                >
                  {evt.title}
                </button>
              ))}
            </div>
          ))}
        </div>
      )}

      {/* Time grid */}
      <div className="flex-1 overflow-y-auto">
        <div className="flex relative" style={{ height: `${24 * HOUR_HEIGHT}px` }}>
          {/* Time gutter */}
          <div className="w-16 flex-shrink-0 relative">
            {HOURS.map((h) => (
              <div
                key={h}
                className="absolute w-full text-right pr-2 text-[10px] text-gray-400 dark:text-gray-500 -mt-2"
                style={{ top: `${h * HOUR_HEIGHT}px` }}
              >
                {h === 0 ? "" : format(new Date(2000, 0, 1, h), "h a")}
              </div>
            ))}
          </div>

          {/* Day columns */}
          {weekDays.map((day) => (
            <div
              key={day.toISOString()}
              className="flex-1 relative border-l border-gray-100 dark:border-gray-700/50"
            >
              {HOURS.map((h) => (
                <div
                  key={h}
                  className="absolute w-full border-t border-gray-100 dark:border-gray-700/30 cursor-pointer hover:bg-blue-50/50 dark:hover:bg-blue-900/10"
                  style={{ top: `${h * HOUR_HEIGHT}px`, height: `${HOUR_HEIGHT}px` }}
                  onClick={() => {
                    const d = new Date(day);
                    d.setHours(h, 0, 0, 0);
                    onTimeClick(d);
                  }}
                />
              ))}
              {getEventsForDay(day).map((evt) => {
                const style = getEventStyle(evt);
                return (
                  <button
                    key={evt.id}
                    onClick={(e) => {
                      e.stopPropagation();
                      onEventClick(evt);
                    }}
                    className="absolute left-0.5 right-1 rounded-md px-1.5 py-0.5 text-[11px] text-white font-medium overflow-hidden hover:opacity-90 z-10 shadow-sm"
                    style={{
                      ...style,
                      backgroundColor:
                        calColorMap.get(evt.calendar_id) || "#3B82F6",
                    }}
                  >
                    <div className="truncate">{evt.title}</div>
                    <div className="opacity-75 truncate text-[10px]">
                      {format(parseISO(evt.start_time), "h:mm a")}
                    </div>
                  </button>
                );
              })}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}
