"use client";

import * as React from "react";
import { motion } from "motion/react";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";
import { addDays, addMonths, dayKey, parseDay, startOfMonth } from "@/lib/dates";

const WEEKDAYS = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"];

/**
 * Two-month availability calendar. Taken nights are hatched, the selected
 * stay is highlighted, and tapping days picks a check-in then a check-out.
 */
export function AvailabilityCalendar({ booked, checkIn, checkOut, today, onPick, month, onMonth }: { booked: Set<string>; checkIn: string; checkOut: string; today: string; onPick: (day: string) => void; month: Date; onMonth: (m: Date) => void }) {
  const months = [month, addMonths(month, 1)];
  const canBack = dayKey(month) > dayKey(startOfMonth(parseDay(today)));
  return (
    <div>
      <div className="mb-2 flex items-center justify-between">
        <button type="button" onClick={() => canBack && onMonth(addMonths(month, -1))} disabled={!canBack} className="rounded-md p-1.5 text-fg-muted transition hover:bg-surface-2 hover:text-fg disabled:opacity-30" aria-label="Previous month">
          <ChevronLeft className="size-4" />
        </button>
        <p className="text-xs text-fg-muted">Tap a check-in day, then a check-out day</p>
        <button type="button" onClick={() => onMonth(addMonths(month, 1))} className="rounded-md p-1.5 text-fg-muted transition hover:bg-surface-2 hover:text-fg" aria-label="Next month">
          <ChevronRight className="size-4" />
        </button>
      </div>
      <div className="grid gap-4 sm:grid-cols-2">
        {months.map((m) => (
          <Month key={dayKey(m)} month={m} booked={booked} checkIn={checkIn} checkOut={checkOut} today={today} onPick={onPick} />
        ))}
      </div>
      <div className="mt-3 flex flex-wrap items-center gap-3 text-2xs text-fg-muted">
        <span className="flex items-center gap-1"><span className="size-3 rounded-sm bg-surface-3" /> Free</span>
        <span className="flex items-center gap-1"><span className="size-3 rounded-sm bg-[repeating-linear-gradient(45deg,var(--color-negative-500)_0_2px,transparent_2px_5px)] opacity-70" /> Taken</span>
        <span className="flex items-center gap-1"><span className="size-3 rounded-sm bg-primary" /> Your stay</span>
      </div>
    </div>
  );
}

function Month({ month, booked, checkIn, checkOut, today, onPick }: { month: Date; booked: Set<string>; checkIn: string; checkOut: string; today: string; onPick: (day: string) => void }) {
  const first = startOfMonth(month);
  const lead = (first.getUTCDay() + 6) % 7; // Monday-first
  const daysInMonth = new Date(Date.UTC(first.getUTCFullYear(), first.getUTCMonth() + 1, 0)).getUTCDate();
  const cells: (string | null)[] = [...Array(lead).fill(null), ...Array.from({ length: daysInMonth }, (_, i) => dayKey(addDays(first, i)))];
  const title = new Intl.DateTimeFormat("en", { month: "long", year: "numeric", timeZone: "UTC" }).format(first);
  return (
    <div>
      <p className="mb-1.5 text-sm font-semibold">{title}</p>
      <div className="grid grid-cols-7 gap-1 text-center text-[10px] font-medium text-fg-subtle">
        {WEEKDAYS.map((d) => (
          <span key={d}>{d}</span>
        ))}
      </div>
      <div className="mt-1 grid grid-cols-7 gap-1">
        {cells.map((k, i) => {
          if (!k) return <span key={`e${i}`} />;
          const past = k < today;
          const taken = booked.has(k);
          const inStay = checkIn && checkOut ? k >= checkIn && k < checkOut : k === checkIn;
          const edge = k === checkIn || (checkOut && k === dayKey(addDays(parseDay(checkOut), -1)));
          return (
            <motion.button
              key={k}
              type="button"
              disabled={past}
              onClick={() => onPick(k)}
              whileTap={past ? undefined : { scale: 0.9 }}
              className={cn(
                "relative flex aspect-square items-center justify-center rounded-md text-xs tabular transition-colors",
                past ? "text-fg-subtle/50" : "text-fg hover:bg-surface-3",
                !past && taken && "bg-[repeating-linear-gradient(45deg,color-mix(in_oklab,var(--color-negative-500)_55%,transparent)_0_2px,transparent_2px_6px)] text-fg-muted",
                !past && !taken && "bg-surface-2",
                inStay && !past && "bg-primary/20 text-primary",
                edge && !past && "bg-primary text-primary-fg hover:bg-primary",
                k === today && "ring-1 ring-primary/50"
              )}
              aria-label={`${k}${taken ? " taken" : " free"}`}
            >
              {Number(k.slice(-2))}
            </motion.button>
          );
        })}
      </div>
    </div>
  );
}
