"use client";

import { useEffect, useRef, useState } from "react";
import { CalendarDays, ChevronLeft, ChevronRight } from "lucide-react";
import styles from "./DatePicker.module.css";

interface DatePickerProps {
  value: string;
  onChange: (value: string) => void;
  label?: string;
  placeholder?: string;
  required?: boolean;
  id?: string;
}

const WEEKDAYS = ["Lu", "Ma", "Me", "Je", "Ve", "Sa", "Di"];

const MONTHS_FR = [
  "Janvier",
  "Février",
  "Mars",
  "Avril",
  "Mai",
  "Juin",
  "Juillet",
  "Août",
  "Septembre",
  "Octobre",
  "Novembre",
  "Décembre",
];

function parseDate(str: string): Date | null {
  if (!str) return null;
  const d = new Date(str + "T00:00:00");
  return isNaN(d.getTime()) ? null : d;
}

function toISO(date: Date): string {
  const y = date.getFullYear();
  const m = String(date.getMonth() + 1).padStart(2, "0");
  const d = String(date.getDate()).padStart(2, "0");
  return `${y}-${m}-${d}`;
}

function formatDisplay(str: string): string {
  const d = parseDate(str);
  if (!d) return "";
  return d.toLocaleDateString("fr-FR", { day: "2-digit", month: "long", year: "numeric" });
}

export default function DatePicker({ value, onChange, label, placeholder = "Sélectionner une date", required, id }: DatePickerProps) {
  const today = new Date();
  today.setHours(0, 0, 0, 0);

  const [open, setOpen] = useState(false);
  const [viewYear, setViewYear] = useState(parseDate(value)?.getFullYear() ?? today.getFullYear());
  const [viewMonth, setViewMonth] = useState(parseDate(value)?.getMonth() ?? today.getMonth());
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    function onClickOutside(e: MouseEvent) {
      if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);
    }
    if (open) document.addEventListener("mousedown", onClickOutside);
    return () => document.removeEventListener("mousedown", onClickOutside);
  }, [open]);

  useEffect(() => {
    const d = parseDate(value);
    if (d) {
      setViewYear(d.getFullYear());
      setViewMonth(d.getMonth());
    }
  }, [value]);

  const prevMonth = () => {
    if (viewMonth === 0) {
      setViewMonth(11);
      setViewYear((y) => y - 1);
    } else setViewMonth((m) => m - 1);
  };

  const nextMonth = () => {
    if (viewMonth === 11) {
      setViewMonth(0);
      setViewYear((y) => y + 1);
    } else setViewMonth((m) => m + 1);
  };

  const selectDay = (date: Date) => {
    onChange(toISO(date));
    setOpen(false);
  };

  const selectToday = () => {
    onChange(toISO(today));
    setViewYear(today.getFullYear());
    setViewMonth(today.getMonth());
    setOpen(false);
  };

  const clearDate = () => {
    onChange("");
    setOpen(false);
  };

  const firstDay = new Date(viewYear, viewMonth, 1);
  const startDow = (firstDay.getDay() + 6) % 7;
  const daysInMonth = new Date(viewYear, viewMonth + 1, 0).getDate();
  const daysInPrevMonth = new Date(viewYear, viewMonth, 0).getDate();

  const cells: { date: Date; isOther: boolean }[] = [];
  for (let i = startDow - 1; i >= 0; i--) {
    cells.push({ date: new Date(viewYear, viewMonth - 1, daysInPrevMonth - i), isOther: true });
  }
  for (let d = 1; d <= daysInMonth; d++) {
    cells.push({ date: new Date(viewYear, viewMonth, d), isOther: false });
  }
  const remaining = 42 - cells.length;
  for (let d = 1; d <= remaining; d++) {
    cells.push({ date: new Date(viewYear, viewMonth + 1, d), isOther: true });
  }

  const selectedDate = parseDate(value);

  return (
    <div className={styles.field} ref={ref}>
      {label && (
        <label className={styles.label} htmlFor={id}>
          {label}
          {required && <span className={styles.required}>*</span>}
        </label>
      )}

      <button
        id={id}
        type="button"
        className={`${styles.trigger} ${open ? styles.triggerOpen : ""}`}
        onClick={() => setOpen((o) => !o)}
        aria-haspopup="dialog"
        aria-expanded={open}
      >
        <span className={value ? undefined : styles.placeholder}>{value ? formatDisplay(value) : placeholder}</span>
        <CalendarDays size={16} className={styles.calendarIcon} />
      </button>

      {open && (
        <div className={styles.popover} role="dialog" aria-label="Calendrier">
          <div className={styles.nav}>
            <button type="button" className={styles.navBtn} onClick={prevMonth} aria-label="Mois précédent">
              <ChevronLeft size={16} />
            </button>
            <span className={styles.monthLabel}>
              {MONTHS_FR[viewMonth]} {viewYear}
            </span>
            <button type="button" className={styles.navBtn} onClick={nextMonth} aria-label="Mois suivant">
              <ChevronRight size={16} />
            </button>
          </div>

          <div className={styles.weekdays}>
            {WEEKDAYS.map((wd) => (
              <div key={wd} className={styles.weekday}>
                {wd}
              </div>
            ))}
          </div>

          <div className={styles.days}>
            {cells.map(({ date, isOther }, i) => {
              const isSelected = selectedDate && toISO(date) === toISO(selectedDate);
              const isToday = toISO(date) === toISO(today);
              return (
                <button
                  key={i}
                  type="button"
                  onClick={() => selectDay(date)}
                  className={[
                    styles.day,
                    isSelected ? styles.daySelected : "",
                    isToday && !isSelected ? styles.dayToday : "",
                    isOther ? styles.dayOtherMonth : "",
                  ]
                    .filter(Boolean)
                    .join(" ")}
                  aria-pressed={!!isSelected}
                >
                  {date.getDate()}
                </button>
              );
            })}
          </div>

          <div className={styles.footer}>
            <button type="button" className={styles.clearBtn} onClick={clearDate}>
              Effacer
            </button>
            <button type="button" className={styles.todayBtn} onClick={selectToday}>
              Aujourd&apos;hui
            </button>
          </div>
        </div>
      )}
    </div>
  );
}
