"use client";

import { useEffect, useId, useRef, useState } from "react";

type ThemedDatePickerTone = "light" | "dark";

type ThemedDatePickerProps = {
  ariaLabel?: string;
  buttonClassName?: string;
  className?: string;
  defaultValue?: string;
  label?: string;
  labelClassName?: string;
  name?: string;
  onChange?: (value: string) => void;
  required?: boolean;
  tone?: ThemedDatePickerTone;
  value?: string;
};

const FALLBACK_DATE = "2026-05-18";
const monthFormatter = new Intl.DateTimeFormat("en-GB", {
  month: "long",
  year: "numeric",
  timeZone: "UTC",
});
const displayFormatter = new Intl.DateTimeFormat("en-GB", {
  day: "numeric",
  month: "short",
  year: "numeric",
  timeZone: "UTC",
});
const weekdays = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];

function cn(...classes: Array<string | false | null | undefined>) {
  return classes.filter(Boolean).join(" ");
}

function parseIsoDate(value: string) {
  const [year, month, day] = value.split("-").map(Number);

  if (!year || !month || !day) {
    return null;
  }

  return new Date(Date.UTC(year, month - 1, day));
}

function formatIsoDate(year: number, monthIndex: number, day: number) {
  return [
    year.toString().padStart(4, "0"),
    (monthIndex + 1).toString().padStart(2, "0"),
    day.toString().padStart(2, "0"),
  ].join("-");
}

function getMonthState(value: string) {
  const parsed = parseIsoDate(value) ?? parseIsoDate(FALLBACK_DATE);

  return {
    month: parsed?.getUTCMonth() ?? 0,
    year: parsed?.getUTCFullYear() ?? 2026,
  };
}

function formatDisplayDate(value: string) {
  const parsed = parseIsoDate(value);

  return parsed ? displayFormatter.format(parsed) : "Choose date";
}

function getCalendarCells(year: number, month: number) {
  const firstDate = new Date(Date.UTC(year, month, 1));
  const daysInMonth = new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
  const startOffset = (firstDate.getUTCDay() + 6) % 7;
  const cells: Array<number | null> = Array.from({ length: startOffset }, () => null);

  for (let day = 1; day <= daysInMonth; day += 1) {
    cells.push(day);
  }

  while (cells.length % 7 !== 0) {
    cells.push(null);
  }

  return cells;
}

function moveMonth(year: number, month: number, offset: number) {
  const next = new Date(Date.UTC(year, month + offset, 1));

  return {
    month: next.getUTCMonth(),
    year: next.getUTCFullYear(),
  };
}

export function ThemedDatePicker({
  ariaLabel,
  buttonClassName,
  className,
  defaultValue,
  label,
  labelClassName,
  name,
  onChange,
  required,
  tone = "light",
  value,
}: ThemedDatePickerProps) {
  const generatedId = useId();
  const controlled = value !== undefined;
  const [internalValue, setInternalValue] = useState(defaultValue ?? "");
  const selectedValue = controlled ? (value ?? "") : internalValue;
  const [visibleMonth, setVisibleMonth] = useState(() =>
    getMonthState(selectedValue || FALLBACK_DATE),
  );
  const [open, setOpen] = useState(false);
  const pickerRef = useRef<HTMLDivElement>(null);
  const labelId = `${generatedId}-label`;
  const calendarCells = getCalendarCells(visibleMonth.year, visibleMonth.month);
  const monthLabel = monthFormatter.format(
    new Date(Date.UTC(visibleMonth.year, visibleMonth.month, 1)),
  );
  const selectedDate = selectedValue ? parseIsoDate(selectedValue) : null;
  const selectedMonth = selectedDate?.getUTCMonth();
  const selectedYear = selectedDate?.getUTCFullYear();
  const todayValue = FALLBACK_DATE;

  useEffect(() => {
    if (selectedValue) {
      setVisibleMonth(getMonthState(selectedValue));
    }
  }, [selectedValue]);

  useEffect(() => {
    if (!open) {
      return;
    }

    function handlePointerDown(event: PointerEvent) {
      if (
        pickerRef.current &&
        event.target instanceof Node &&
        !pickerRef.current.contains(event.target)
      ) {
        setOpen(false);
      }
    }

    function handleKeyDown(event: KeyboardEvent) {
      if (event.key === "Escape") {
        setOpen(false);
      }
    }

    document.addEventListener("pointerdown", handlePointerDown);
    document.addEventListener("keydown", handleKeyDown);

    return () => {
      document.removeEventListener("pointerdown", handlePointerDown);
      document.removeEventListener("keydown", handleKeyDown);
    };
  }, [open]);

  function commitValue(nextValue: string) {
    if (!controlled) {
      setInternalValue(nextValue);
    }

    onChange?.(nextValue);
  }

  function selectDate(day: number) {
    commitValue(formatIsoDate(visibleMonth.year, visibleMonth.month, day));
    setOpen(false);
  }

  function jumpToToday() {
    commitValue(todayValue);
    setVisibleMonth(getMonthState(todayValue));
    setOpen(false);
  }

  function clearDate() {
    commitValue("");
    setOpen(false);
  }

  return (
    <div className={cn("relative", className)} ref={pickerRef}>
      {label ? (
        <span
          className={cn(
            "block text-sm font-semibold text-foreground",
            tone === "dark" && "text-white/70",
            labelClassName,
          )}
          id={labelId}
        >
          {label}
        </span>
      ) : null}
      {name ? (
        <input
          name={name}
          required={required}
          type="hidden"
          value={selectedValue}
        />
      ) : null}
      <button
        aria-expanded={open}
        aria-haspopup="dialog"
        aria-label={label ? undefined : ariaLabel}
        aria-labelledby={label ? labelId : undefined}
        className={cn(
          "themed-date-control mt-2 flex w-full items-center justify-between gap-3 rounded-[18px] border px-4 py-3 text-left text-sm outline-none transition focus:ring-4",
          tone === "dark"
            ? "border-white/12 bg-[var(--surface-deep)] text-white hover:border-[#c8f06e]/50 focus:border-[#c8f06e]/60 focus:ring-[#c8f06e]/10"
            : "border-border bg-white/78 text-foreground hover:border-primary/35 focus:border-primary/50 focus:ring-primary/10",
          buttonClassName,
        )}
        onClick={() => setOpen((current) => !current)}
        type="button"
      >
        <span
          className={cn(
            selectedValue ? "text-inherit" : "text-muted",
            tone === "dark" && !selectedValue && "text-white/40",
          )}
        >
          {formatDisplayDate(selectedValue)}
        </span>
        <svg
          aria-hidden="true"
          className={cn("h-4 w-4 shrink-0", tone === "dark" ? "text-[#c8f06e]" : "text-primary")}
          fill="none"
          viewBox="0 0 24 24"
        >
          <path
            d="M7 3v3M17 3v3M4.5 9.5h15M6.5 5.5h11A2.5 2.5 0 0 1 20 8v10a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 4 18V8a2.5 2.5 0 0 1 2.5-2.5Z"
            stroke="currentColor"
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth="1.8"
          />
        </svg>
      </button>

      {open ? (
        <>
          <button
            aria-label="Close calendar"
            className="themed-date-backdrop fixed inset-0 z-[210] border-0 sm:hidden"
            onClick={() => setOpen(false)}
            type="button"
          />
          <div
            aria-label={label ? `${label} calendar` : (ariaLabel ?? "Calendar")}
            className={cn(
              "themed-date-panel absolute left-0 right-0 z-[220] mt-2 rounded-[24px] border p-3 shadow-[0_24px_70px_rgba(0,0,0,0.22)]",
              tone === "dark"
                ? "border-white/12 bg-[#102631]/95 text-white"
                : "border-[#143569]/14 bg-[#fffaf1]/95 text-[#10233f]",
            )}
            role="dialog"
            style={{ colorScheme: tone === "dark" ? "dark" : "light" }}
          >
          <div className="flex items-center justify-between gap-3">
            <button
              className={cn(
                "themed-date-control grid h-10 w-10 place-items-center rounded-full border transition",
                tone === "dark"
                  ? "border-white/12 text-white/70 hover:border-[#c8f06e]/45 hover:text-[#c8f06e]"
                  : "border-[#143569]/12 text-[#143569] hover:bg-[#143569] hover:text-[#fffaf1]",
              )}
              onClick={() => setVisibleMonth((current) => moveMonth(current.year, current.month, -1))}
              type="button"
            >
              <span className="sr-only">Previous month</span>
              &lt;
            </button>
            <p className="text-sm font-semibold tracking-tight">{monthLabel}</p>
            <button
              className={cn(
                "themed-date-control grid h-10 w-10 place-items-center rounded-full border transition",
                tone === "dark"
                  ? "border-white/12 text-white/70 hover:border-[#c8f06e]/45 hover:text-[#c8f06e]"
                  : "border-[#143569]/12 text-[#143569] hover:bg-[#143569] hover:text-[#fffaf1]",
              )}
              onClick={() => setVisibleMonth((current) => moveMonth(current.year, current.month, 1))}
              type="button"
            >
              <span className="sr-only">Next month</span>
              &gt;
            </button>
          </div>

          <div className="mt-4 grid grid-cols-7 gap-1 text-center text-[10px] font-semibold uppercase tracking-[0.16em] text-muted">
            {weekdays.map((weekday) => (
              <span key={weekday}>{weekday}</span>
            ))}
          </div>

          <div className="mt-2 grid grid-cols-7 gap-1">
            {calendarCells.map((day, index) => {
              const isoValue = day
                ? formatIsoDate(visibleMonth.year, visibleMonth.month, day)
                : "";
              const selected =
                Boolean(day) &&
                selectedYear === visibleMonth.year &&
                selectedMonth === visibleMonth.month &&
                selectedDate?.getUTCDate() === day;
              const today = isoValue === todayValue;

              return day ? (
                <button
                  className={cn(
                    "themed-date-control themed-date-day grid h-10 place-items-center rounded-2xl text-xs font-semibold transition",
                    tone === "dark"
                      ? "text-white/78 hover:bg-white/10"
                      : "text-[#36465e] hover:bg-[#eadfce]",
                    today &&
                      (tone === "dark"
                        ? "ring-1 ring-[#c8f06e]/50"
                        : "ring-1 ring-[#143569]/30"),
                    selected &&
                      (tone === "dark"
                        ? "bg-[#c8f06e] text-[#0d2029] hover:bg-[#c8f06e]"
                        : "bg-[#143569] text-[#fffaf1] hover:bg-[#143569]"),
                  )}
                  key={isoValue}
                  onClick={() => selectDate(day)}
                  type="button"
                >
                  {day}
                </button>
              ) : (
                <span aria-hidden="true" key={`blank-${index}`} />
              );
            })}
          </div>

          <div className="mt-4 flex items-center justify-between gap-2 border-t border-current/10 pt-3">
            <button
              className={cn(
                "themed-date-control rounded-full px-3 py-2 text-xs font-semibold transition",
                tone === "dark"
                  ? "text-white/58 hover:bg-white/10 hover:text-white"
                  : "text-[#65717f] hover:bg-[#eadfce] hover:text-[#143569]",
              )}
              onClick={clearDate}
              type="button"
            >
              Clear
            </button>
            <button
              className={cn(
                "themed-date-control rounded-full px-3 py-2 text-xs font-semibold transition",
                tone === "dark"
                  ? "bg-[#c8f06e] text-[#0d2029] hover:bg-white"
                  : "bg-[#143569] text-[#fffaf1] hover:bg-[#0f2852]",
              )}
              onClick={jumpToToday}
              type="button"
            >
              Today
            </button>
          </div>
          </div>
        </>
      ) : null}
    </div>
  );
}
