"use client";

import { useState } from "react";

import { cn } from "@/lib/utils";
import { useTranslation } from "@/hooks/useTranslation";
import { Spinner } from "@/components/ui/spinner";

import { CalendarToolbar } from "./calendar-toolbar";
import { CalendarDialog, type CalendarDialogView } from "./calendar-dialog";
import { MonthView } from "./views/month-view";
import { WeekView } from "./views/week-view";
import { DayView } from "./views/day-view";
import { useCalendar } from "./hooks/use-calendar";
import { CALENDAR_VIEWS, DAY_END_HOUR, DAY_START_HOUR } from "./constants";
import {
  getDateLocale,
  getPeriodLabel,
  resolveWeekStartsOn,
} from "./lib/date-utils";
import type { CalendarEvent, CalendarProps } from "./types";

/**
 * Reusable, data-agnostic calendar with month / week / day views. Feed it
 * `events` and (optionally) control `view`/`date`; everything else — locale,
 * RTL, navigation, overlap layout, the detail dialog — is handled internally.
 * Screen-specific filters go in the `toolbar` slot (same idea as DataTable).
 */
export function Calendar<TMeta = unknown>({
  events,
  view: viewProp,
  onViewChange,
  defaultView = "month",
  date: dateProp,
  onDateChange,
  defaultDate,
  availableViews = CALENDAR_VIEWS,
  weekStartsOn: weekStartsOnProp,
  onEventClick,
  onSelectSlot,
  renderEvent,
  renderEventDetail,
  toolbar,
  loading = false,
  emptyState,
  className,
}: CalendarProps<TMeta>) {
  const { t, language } = useTranslation();

  const { view, date, setView, setDate, goToday, goPrev, goNext } = useCalendar(
    {
      view: viewProp,
      onViewChange,
      defaultView,
      date: dateProp,
      onDateChange,
      defaultDate,
    },
  );

  const locale = getDateLocale(language);
  const weekStartsOn = resolveWeekStartsOn(weekStartsOnProp, locale);
  const label = getPeriodLabel(date, view, locale, weekStartsOn);

  // One dialog, two views (day list ↔ event detail) so swapping between them
  // never closes/reopens the dialog — and drilling in keeps a Back target.
  const [dialogView, setDialogView] =
    useState<CalendarDialogView<TMeta> | null>(null);

  /** `fromDate` is set when the event was opened from a day list (enables Back). */
  const handleEventClick = (
    event: CalendarEvent<TMeta>,
    fromDate: Date | null = null,
  ) => {
    if (onEventClick) {
      setDialogView(null);
      onEventClick(event);
      return;
    }
    setDialogView({ type: "event", event, fromDate });
  };

  const handleSelectDay = (day: Date) => {
    onSelectSlot?.(day);
    setDialogView({ type: "day", date: day });
  };

  const openDayView = (day: Date) => {
    setDialogView(null);
    setDate(day);
    setView("day");
  };

  const moreLabel = (count: number) => t("calendar.moreEvents", { count });

  const showEmpty = !loading && !!emptyState && events.length === 0;

  return (
    <div
      className={cn(
        "flex min-w-0 flex-col overflow-hidden rounded-[12px] border border-border bg-white",
        className,
      )}
    >
      <CalendarToolbar
        label={label}
        view={view}
        views={availableViews}
        onViewChange={setView}
        onToday={goToday}
        onPrev={goPrev}
        onNext={goNext}
        filters={toolbar}
      />

      <div className="relative flex min-h-0 flex-1 flex-col">
        {showEmpty ? (
          <div className="flex flex-1 items-center justify-center p-8">
            {emptyState}
          </div>
        ) : view === "month" ? (
          <MonthView
            date={date}
            events={events}
            locale={locale}
            weekStartsOn={weekStartsOn}
            onEventClick={handleEventClick}
            onSelectDay={handleSelectDay}
            renderEvent={renderEvent}
            moreLabel={moreLabel}
          />
        ) : view === "week" ? (
          <WeekView
            date={date}
            events={events}
            locale={locale}
            weekStartsOn={weekStartsOn}
            startHour={DAY_START_HOUR}
            endHour={DAY_END_HOUR}
            allDayLabel={t("calendar.allDay")}
            onEventClick={handleEventClick}
            onSelectSlot={onSelectSlot}
            renderEvent={renderEvent}
          />
        ) : (
          <DayView
            date={date}
            events={events}
            locale={locale}
            startHour={DAY_START_HOUR}
            endHour={DAY_END_HOUR}
            allDayLabel={t("calendar.allDay")}
            onEventClick={handleEventClick}
            onSelectSlot={onSelectSlot}
            renderEvent={renderEvent}
          />
        )}

        {loading && (
          <div className="absolute inset-0 z-30 flex items-center justify-center bg-white/60">
            <Spinner />
          </div>
        )}
      </div>

      <CalendarDialog
        view={dialogView}
        events={events}
        locale={locale}
        onClose={() => setDialogView(null)}
        onSelectEvent={handleEventClick}
        onBack={(date) => setDialogView({ type: "day", date })}
        onViewDay={openDayView}
        renderEvent={renderEvent}
        renderEventDetail={renderEventDetail}
      />
    </div>
  );
}
