import * as React from "react";
import * as Popover from "@radix-ui/react-popover";
import {
  Calendar as CalendarIcon,
  ChevronLeft,
  ChevronRight,
} from "lucide-react";
import {
  addMonths,
  eachDayOfInterval,
  endOfMonth,
  endOfWeek,
  format,
  isSameDay,
  isSameMonth,
  isToday,
  parseISO,
  startOfMonth,
  startOfWeek,
  subMonths,
} from "date-fns";
import { fr } from "date-fns/locale";

import { cn } from "@/lib/utils";

/**
 * DatePicker brandé Rubis — alternative au natif `<input type="date">` qui
 * affiche le calendrier moche du navigateur. Utilise Radix Popover pour le
 * positionnement et l'accessibilité (focus trap, Escape, click outside).
 *
 * Palette : trigger en `Input`-style (border line, focus rubis), grille avec
 * jour sélectionné `bg-rubis text-white` + ombre rubis, today `ring-rubis-glow`.
 *
 * I/O :
 *  - `value` accepte string ISO (cf. usage existant Tanstack Form) ou `Date`.
 *  - `onChange(date: Date)` rend toujours un Date que l'appelant convertit
 *    via `.toISOString()` ou autre format selon son champ.
 */
export type DatePickerProps = {
  value?: string | Date | null;
  onChange: (date: Date) => void;
  placeholder?: string;
  id?: string;
  className?: string;
  disabled?: boolean;
  "aria-invalid"?: boolean;
};

function toDate(value: DatePickerProps["value"]): Date | null {
  if (!value) return null;
  if (value instanceof Date) return value;
  try {
    const d = parseISO(value);
    return Number.isNaN(d.getTime()) ? null : d;
  } catch {
    return null;
  }
}

export function DatePicker({
  value,
  onChange,
  placeholder = "Choisir une date",
  id,
  className,
  disabled,
  "aria-invalid": ariaInvalid,
}: DatePickerProps) {
  const date = toDate(value);
  const [open, setOpen] = React.useState(false);
  const [viewMonth, setViewMonth] = React.useState<Date>(date ?? new Date());

  // Re-sync viewMonth quand la valeur externe change (reset de form, etc.)
  React.useEffect(() => {
    if (date) setViewMonth(date);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [date?.getTime()]);

  const handleSelect = (d: Date) => {
    onChange(d);
    setOpen(false);
  };

  return (
    <Popover.Root open={open} onOpenChange={setOpen}>
      <Popover.Trigger asChild>
        <button
          id={id}
          type="button"
          disabled={disabled}
          aria-invalid={ariaInvalid}
          className={cn(
            // Base — alignée avec Input.tsx pour cohérence visuelle
            "flex w-full items-center justify-between gap-2 rounded-default border border-line bg-white px-3.5 py-3 text-left",
            "font-sans text-base lg:text-[15px]",
            // Transitions
            "transition-[border-color,box-shadow] duration-150",
            // Focus
            "focus:outline-none focus:border-rubis focus:ring-4 focus:ring-rubis-glow",
            // Open state — petit hint visuel
            "data-[state=open]:border-rubis data-[state=open]:ring-4 data-[state=open]:ring-rubis-glow",
            // États
            "disabled:cursor-not-allowed disabled:bg-cream-2 disabled:text-ink-3",
            "aria-[invalid=true]:border-rubis-deep aria-[invalid=true]:bg-rubis-glow/30",
            className,
          )}
        >
          <span className={cn(date ? "text-ink" : "text-ink-3")}>
            {date
              ? format(date, "d MMMM yyyy", { locale: fr })
              : placeholder}
          </span>
          <CalendarIcon className="h-4 w-4 shrink-0 text-ink-3" aria-hidden />
        </button>
      </Popover.Trigger>
      <Popover.Portal>
        <Popover.Content
          align="start"
          sideOffset={6}
          className={cn(
            "z-50 w-[20rem] rounded-default border border-line bg-white p-3",
            "shadow-[0_8px_24px_rgba(26,20,16,0.10)]",
            // Animation discrète
            "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
            "data-[state=closed]:animate-out data-[state=closed]:fade-out-0",
          )}
        >
          <CalendarGrid
            viewMonth={viewMonth}
            selectedDate={date}
            onSelect={handleSelect}
            onMonthChange={setViewMonth}
          />
        </Popover.Content>
      </Popover.Portal>
    </Popover.Root>
  );
}

// ---------------------------------------------------------------------------
// Grille interne — header (chevrons + mois courant) + 7×6 jours + raccourci
// "Aujourd'hui". Semaine commence lundi (FR).
// ---------------------------------------------------------------------------

type CalendarGridProps = {
  viewMonth: Date;
  selectedDate: Date | null;
  onSelect: (date: Date) => void;
  onMonthChange: (date: Date) => void;
};

function CalendarGrid({
  viewMonth,
  selectedDate,
  onSelect,
  onMonthChange,
}: CalendarGridProps) {
  const monthStart = startOfMonth(viewMonth);
  const monthEnd = endOfMonth(viewMonth);
  const gridStart = startOfWeek(monthStart, { weekStartsOn: 1 }); // Lundi
  const gridEnd = endOfWeek(monthEnd, { weekStartsOn: 1 });

  const days = eachDayOfInterval({ start: gridStart, end: gridEnd });
  const weekDays = ["L", "M", "M", "J", "V", "S", "D"];

  return (
    <div>
      {/* Header mois — chevrons + label */}
      <div className="mb-3 flex items-center justify-between">
        <button
          type="button"
          onClick={() => onMonthChange(subMonths(viewMonth, 1))}
          className="rounded-default p-1.5 text-ink-2 transition-colors hover:bg-cream hover:text-rubis focus:outline-none focus:ring-2 focus:ring-rubis-glow"
          aria-label="Mois précédent"
        >
          <ChevronLeft className="h-4 w-4" />
        </button>
        <div className="text-sm font-semibold capitalize text-ink">
          {format(viewMonth, "MMMM yyyy", { locale: fr })}
        </div>
        <button
          type="button"
          onClick={() => onMonthChange(addMonths(viewMonth, 1))}
          className="rounded-default p-1.5 text-ink-2 transition-colors hover:bg-cream hover:text-rubis focus:outline-none focus:ring-2 focus:ring-rubis-glow"
          aria-label="Mois suivant"
        >
          <ChevronRight className="h-4 w-4" />
        </button>
      </div>

      {/* Labels jours (L M M J V S D) */}
      <div className="mb-2 grid grid-cols-7">
        {weekDays.map((d, i) => (
          <div
            key={i}
            className="text-center text-[11px] font-semibold uppercase tracking-wider text-ink-3"
          >
            {d}
          </div>
        ))}
      </div>

      {/* Grille 7×6 jours */}
      <div className="grid grid-cols-7 gap-1">
        {days.map((day) => {
          const isOutside = !isSameMonth(day, viewMonth);
          const isSelected = selectedDate ? isSameDay(day, selectedDate) : false;
          const isCurrent = isToday(day);
          return (
            <button
              key={day.toISOString()}
              type="button"
              onClick={() => onSelect(day)}
              className={cn(
                "aspect-square w-full rounded-default text-sm font-medium tabular-nums",
                "transition-colors duration-100",
                "focus:outline-none focus:ring-2 focus:ring-rubis-glow",
                // Jour hors mois courant — discret
                isOutside && !isSelected && "text-ink-3/50",
                // Jour normal du mois — hover crème
                !isOutside && !isSelected && "text-ink hover:bg-cream",
                // Today (non sélectionné) — petit ring rubis-glow pour repère
                isCurrent && !isSelected && "ring-1 ring-inset ring-rubis-glow",
                // Sélectionné — bg rubis + glow
                isSelected &&
                  "bg-rubis text-white shadow-[0_2px_8px_rgba(159,18,57,0.30)]",
              )}
              aria-pressed={isSelected || undefined}
              aria-current={isCurrent ? "date" : undefined}
            >
              {format(day, "d")}
            </button>
          );
        })}
      </div>

      {/* Raccourci "Aujourd'hui" */}
      <div className="mt-3 border-t border-line pt-3">
        <button
          type="button"
          onClick={() => onSelect(new Date())}
          className="w-full rounded-default py-1.5 text-sm font-semibold text-rubis transition-colors hover:bg-rubis-glow/40 hover:text-rubis-deep focus:outline-none focus:ring-2 focus:ring-rubis-glow"
        >
          Aujourd&apos;hui
        </button>
      </div>
    </div>
  );
}
