"use client";

import type { ReactNode } from "react";
import type { Locale } from "date-fns";

import { cn } from "@/lib/utils";
import { Typography } from "@/components/ui/typography";

import { EventChip } from "../event-chip";
import { MONTH_CELL_MAX_EVENTS } from "../constants";
import {
  formatDayNumber,
  getMonthWeeks,
  getWeekdayLabels,
  isSameMonth,
  isToday,
  type WeekStart,
} from "../lib/date-utils";
import { getDayEvents } from "../lib/event-layout";
import type { CalendarEvent } from "../types";

interface MonthViewProps<TMeta> {
  date: Date;
  events: CalendarEvent<TMeta>[];
  locale: Locale;
  weekStartsOn: WeekStart;
  onEventClick: (event: CalendarEvent<TMeta>) => void;
  onSelectDay: (day: Date) => void;
  renderEvent?: (event: CalendarEvent<TMeta>) => ReactNode;
  moreLabel: (count: number) => string;
}

export function MonthView<TMeta>({
  date,
  events,
  locale,
  weekStartsOn,
  onEventClick,
  onSelectDay,
  renderEvent,
  moreLabel,
}: MonthViewProps<TMeta>) {
  const weeks = getMonthWeeks(date, weekStartsOn);
  const weekdays = getWeekdayLabels(locale, weekStartsOn);

  return (
    <div className="flex min-h-0 flex-1 flex-col">
      {/* Weekday header — short label on wider screens, narrow on phones */}
      <div className="grid grid-cols-7 border-b border-border">
        {weekdays.map((weekday, i) => (
          <div key={i} className="px-1 py-2 text-center">
            <Typography as="span" variant="caption" color="secondary">
              <span className="hidden sm:inline">{weekday.short}</span>
              <span className="sm:hidden">{weekday.narrow}</span>
            </Typography>
          </div>
        ))}
      </div>

      {/* Day grid */}
      <div className="grid min-h-0 flex-1 auto-rows-fr grid-cols-7">
        {weeks.flat().map((day) => {
          const { allDay, timed } = getDayEvents(events, day);
          const dayEvents = [...allDay, ...timed];
          const visible = dayEvents.slice(0, MONTH_CELL_MAX_EVENTS);
          const hidden = dayEvents.length - visible.length;
          const inMonth = isSameMonth(day, date);
          const today = isToday(day);

          return (
            <div
              key={day.toISOString()}
              role="gridcell"
              onClick={() => onSelectDay(day)}
              className={cn(
                "flex min-h-16 cursor-pointer flex-col gap-1 border-e border-b border-border p-1.5 md:min-h-24",
                !inMonth && "bg-muted/40",
              )}
            >
              <div className="flex justify-end">
                <span
                  className={cn(
                    "flex size-6 items-center justify-center rounded-full",
                    today && "bg-primary",
                  )}
                >
                  <Typography
                    as="span"
                    variant="number"
                    color="inherit"
                    className={cn(
                      "text-[13px]",
                      today
                        ? "text-primary-foreground"
                        : inMonth
                          ? "text-main-text"
                          : "text-secondary-text",
                    )}
                  >
                    {formatDayNumber(day, locale)}
                  </Typography>
                </span>
              </div>

              <div className="flex flex-col gap-0.5 overflow-hidden">
                {visible.map((event) => (
                  <EventChip
                    key={event.id}
                    event={event}
                    locale={locale}
                    onClick={onEventClick}
                    renderEvent={renderEvent}
                  />
                ))}
                {hidden > 0 && (
                  <button
                    type="button"
                    className="px-1 text-start hover:underline"
                    onClick={(e) => {
                      e.stopPropagation();
                      onSelectDay(day);
                    }}
                  >
                    <Typography as="span" variant="caption" color="secondary">
                      {moreLabel(hidden)}
                    </Typography>
                  </button>
                )}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}
