"use client";

import type { ReactNode } from "react";
import { ArrowLeftIcon, CalendarDaysIcon } from "lucide-react";
import { format, type Locale } from "date-fns";

import { cn } from "@/lib/utils";
import { useTranslation } from "@/hooks/useTranslation";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogBody,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { EmptyState } from "@/components/ui/empty-state";

import { DayEventsList } from "./day-events-list";
import { DEFAULT_EVENT_COLOR, EVENT_COLOR_CLASSES } from "./constants";
import { formatTimeRange } from "./lib/date-utils";
import { getDayEvents } from "./lib/event-layout";
import type { CalendarEvent } from "./types";

/** Which screen the single calendar dialog is showing. */
export type CalendarDialogView<TMeta> =
  | { type: "day"; date: Date }
  | { type: "event"; event: CalendarEvent<TMeta>; fromDate: Date | null };

interface CalendarDialogProps<TMeta> {
  view: CalendarDialogView<TMeta> | null;
  events: CalendarEvent<TMeta>[];
  locale: Locale;
  onClose: () => void;
  /** A row in the day list was chosen → drill into that event. */
  onSelectEvent: (event: CalendarEvent<TMeta>, fromDate: Date) => void;
  /** Back from an event to the day list it was opened from. */
  onBack: (date: Date) => void;
  /** "View day" → switch the calendar itself to the day view. */
  onViewDay: (date: Date) => void;
  renderEvent?: (event: CalendarEvent<TMeta>) => ReactNode;
  renderEventDetail?: (event: CalendarEvent<TMeta>) => ReactNode;
}

/**
 * ONE dialog for both calendar pop-ups — the day's booking list and a single
 * event's detail. Swapping views keeps the same Dialog mounted, so there's no
 * close/re-open flash between them, and drilling in from the list gets a real
 * Back button instead of stranding the user.
 */
export function CalendarDialog<TMeta>({
  view,
  events,
  locale,
  onClose,
  onSelectEvent,
  onBack,
  onViewDay,
  renderEvent,
  renderEventDetail,
}: CalendarDialogProps<TMeta>) {
  const { t } = useTranslation();

  const dayView = view?.type === "day" ? view : null;
  const eventView = view?.type === "event" ? view : null;
  const backDate = eventView?.fromDate ?? null;

  const dayEvents = dayView
    ? (() => {
        const { allDay, timed } = getDayEvents(events, dayView.date);
        return [...allDay, ...timed];
      })()
    : [];

  return (
    <Dialog open={view !== null} onOpenChange={(open) => !open && onClose()}>
      <DialogContent>
        {dayView && (
          <>
            <DialogHeader>
              <DialogTitle>
                {format(dayView.date, "EEEE, d LLLL yyyy", { locale })}
              </DialogTitle>
              {dayEvents.length > 0 && (
                <DialogDescription>
                  {t("calendar.bookingsCount", { count: dayEvents.length })}
                </DialogDescription>
              )}
            </DialogHeader>

            <DialogBody>
              {dayEvents.length > 0 ? (
                <DayEventsList
                  events={dayEvents}
                  locale={locale}
                  renderEvent={renderEvent}
                  onSelect={(event) => onSelectEvent(event, dayView.date)}
                />
              ) : (
                <EmptyState
                  size="sm"
                  icon={<CalendarDaysIcon strokeWidth={1.5} />}
                  title={t("calendar.noEvents")}
                />
              )}
            </DialogBody>

            <DialogFooter>
              <Button
                type="button"
                className="w-full gap-2"
                onClick={() => onViewDay(dayView.date)}
              >
                <CalendarDaysIcon className="size-4" />
                {t("calendar.viewDay")}
              </Button>
            </DialogFooter>
          </>
        )}

        {eventView && (
          <>
            <DialogHeader>
              <div className="flex items-center gap-1">
                {backDate && (
                  <Button
                    type="button"
                    variant="ghost"
                    size="icon-sm"
                    className="-ms-1 shrink-0"
                    aria-label={t("common.back")}
                    onClick={() => onBack(backDate)}
                  >
                    <ArrowLeftIcon className="rtl:rotate-180" />
                  </Button>
                )}
                <DialogTitle className="flex min-w-0 items-center gap-2">
                  <span
                    className={cn(
                      "size-2.5 shrink-0 rounded-full",
                      EVENT_COLOR_CLASSES[
                        eventView.event.color ?? DEFAULT_EVENT_COLOR
                      ].dot,
                    )}
                    aria-hidden
                  />
                  <span className="truncate">{eventView.event.title}</span>
                </DialogTitle>
              </div>
              <DialogDescription>
                {[
                  format(eventView.event.start, "EEEE, d LLLL yyyy", {
                    locale,
                  }),
                  eventView.event.allDay
                    ? t("calendar.allDay")
                    : formatTimeRange(
                        eventView.event.start,
                        eventView.event.end,
                        locale,
                      ),
                ].join(" · ")}
              </DialogDescription>
            </DialogHeader>

            <DialogBody>{renderEventDetail?.(eventView.event)}</DialogBody>
          </>
        )}
      </DialogContent>
    </Dialog>
  );
}
