"use client";

import * as React from "react";

import { format, isValid, parse, parseISO } from "date-fns";
import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon, ClockIcon } from "lucide-react";
import type { DateRange } from "react-day-picker";

import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { cn } from "@/lib/utils";

const MONTH_SHORT = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] as const;

interface DateRangePickerProps {
  value?: DateRange;
  onChange?: (value: DateRange | undefined) => void;
  placeholder?: string;
  className?: string;
  align?: "start" | "center" | "end";
}

export function DateRangePicker({
  value,
  onChange,
  placeholder = "Select date",
  className,
  align = "end",
}: DateRangePickerProps) {
  const [open, setOpen] = React.useState(false);
  const [internalDateRange, setInternalDateRange] = React.useState<DateRange | undefined>();
  const isControlled = onChange !== undefined;
  const dateRange = isControlled ? value : (value ?? internalDateRange);

  const handleDateChange = (nextValue: DateRange | undefined) => {
    if (!isControlled) {
      setInternalDateRange(nextValue);
    }
    onChange?.(nextValue);
  };

  const label = dateRange?.from
    ? dateRange.to
      ? `${format(dateRange.from, "d MMM yyyy")} - ${format(dateRange.to, "d MMM yyyy")}`
      : format(dateRange.from, "d MMM yyyy")
    : placeholder;

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button variant="outline" className={cn("font-normal", className)}>
          {label}
        </Button>
      </PopoverTrigger>
      <PopoverContent className="w-auto overflow-hidden p-0" align={align}>
        <Calendar
          mode="range"
          defaultMonth={dateRange?.from}
          selected={dateRange}
          onSelect={handleDateChange}
          numberOfMonths={2}
          showOutsideDays={false}
        />
      </PopoverContent>
    </Popover>
  );
}

function parseDateValue(value?: string): Date | undefined {
  if (!value?.trim()) return undefined;
  const trimmed = value.trim();

  const iso = parseISO(trimmed);
  if (isValid(iso)) return iso;

  const sqlDateTime = parse(trimmed, "yyyy-MM-dd HH:mm:ss", new Date());
  if (isValid(sqlDateTime)) return sqlDateTime;

  const dashDate = parse(trimmed, "dd-MM-yyyy", new Date());
  if (isValid(dashDate)) return dashDate;

  const slashDate = parse(trimmed, "dd/MM/yyyy", new Date());
  if (isValid(slashDate)) return slashDate;

  const longDate = new Date(trimmed);
  return isValid(longDate) ? longDate : undefined;
}

interface DatePickerProps {
  value?: string;
  onChange?: (value: string) => void;
  placeholder?: string;
  className?: string;
  align?: "start" | "center" | "end";
  id?: string;
  "aria-invalid"?: boolean;
}

/** Single-date picker — same popover/calendar pattern as stock list DateRangePicker. */
export function DatePicker({
  value,
  onChange,
  placeholder = "Select date",
  className,
  align = "start",
  id,
  "aria-invalid": ariaInvalid,
}: DatePickerProps) {
  const [open, setOpen] = React.useState(false);
  const selected = parseDateValue(value);
  const now = new Date();

  const label = selected ? format(selected, "d MMM yyyy") : placeholder;

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button
          type="button"
          variant="outline"
          id={id}
          aria-invalid={ariaInvalid}
          className={cn("h-8 w-full gap-2 font-normal", className)}
        >
          <span className={cn("min-w-0 flex-1 truncate text-left", !selected && "text-muted-foreground")}>
            {label}
          </span>
          <CalendarIcon className="size-3.5 shrink-0 text-muted-foreground" />
        </Button>
      </PopoverTrigger>
      <PopoverContent className="w-auto overflow-hidden p-0" align={align}>
        <Calendar
          mode="single"
          defaultMonth={selected ?? now}
          selected={selected}
          onSelect={(date) => {
            onChange?.(date ? format(date, "yyyy-MM-dd") : "");
            setOpen(false);
          }}
        />
        <div className="flex items-center justify-between border-t px-3 py-2">
          <button
            type="button"
            className="text-primary text-sm hover:underline"
            onClick={() => {
              onChange?.("");
              setOpen(false);
            }}
          >
            Clear
          </button>
          <button
            type="button"
            className="text-primary text-sm hover:underline"
            onClick={() => {
              onChange?.(format(now, "yyyy-MM-dd"));
              setOpen(false);
            }}
          >
            Today
          </button>
        </div>
      </PopoverContent>
    </Popover>
  );
}

function parseTimeValue(value?: string): { hour: number; minute: number } | undefined {
  if (!value?.trim()) return undefined;
  const m = /^(\d{1,2}):(\d{2})(?::\d{2})?$/.exec(value.trim());
  if (!m) return undefined;
  const hour = Number(m[1]);
  const minute = Number(m[2]);
  if (!Number.isInteger(hour) || hour < 0 || hour > 23) return undefined;
  if (!Number.isInteger(minute) || minute < 0 || minute > 59) return undefined;
  return { hour, minute };
}

interface TimePickerProps {
  value?: string;
  onChange?: (value: string) => void;
  placeholder?: string;
  className?: string;
  align?: "start" | "center" | "end";
  id?: string;
  "aria-invalid"?: boolean;
}

/** 24h time picker (HH:mm) — same trigger/footer pattern as DatePicker. */
export function TimePicker({
  value,
  onChange,
  placeholder = "Select time",
  className,
  align = "start",
  id,
  "aria-invalid": ariaInvalid,
}: TimePickerProps) {
  const [open, setOpen] = React.useState(false);
  const selected = parseTimeValue(value);
  const now = new Date();
  const [hour, setHour] = React.useState(selected?.hour ?? now.getHours());
  const [minute, setMinute] = React.useState(selected?.minute ?? now.getMinutes());

  React.useEffect(() => {
    if (selected) {
      setHour(selected.hour);
      setMinute(selected.minute);
    }
  }, [selected?.hour, selected?.minute]);

  const label = selected
    ? `${String(selected.hour).padStart(2, "0")}:${String(selected.minute).padStart(2, "0")}`
    : placeholder;

  const commit = (nextHour: number, nextMinute: number) => {
    onChange?.(
      `${String(nextHour).padStart(2, "0")}:${String(nextMinute).padStart(2, "0")}`,
    );
  };

  return (
    <Popover
      open={open}
      onOpenChange={(next) => {
        setOpen(next);
        if (next) {
          setHour(selected?.hour ?? now.getHours());
          setMinute(selected?.minute ?? now.getMinutes());
        }
      }}
    >
      <PopoverTrigger asChild>
        <Button
          type="button"
          variant="outline"
          id={id}
          aria-invalid={ariaInvalid}
          className={cn("h-8 w-full gap-2 font-normal", className)}
        >
          <span className={cn("min-w-0 flex-1 truncate text-left", !selected && "text-muted-foreground")}>
            {label}
          </span>
          <ClockIcon className="size-3.5 shrink-0 text-muted-foreground" />
        </Button>
      </PopoverTrigger>
      <PopoverContent className="w-[220px] overflow-hidden p-0" align={align}>
        <div className="grid grid-cols-2 gap-2 p-3">
          <div className="space-y-1">
            <p className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">Hour</p>
            <div className="h-40 overflow-y-auto rounded-md border border-border/60">
              {Array.from({ length: 24 }, (_, h) => (
                <button
                  key={h}
                  type="button"
                  className={cn(
                    "flex w-full items-center justify-center px-2 py-1.5 text-sm tabular-nums hover:bg-muted",
                    hour === h && "bg-primary text-primary-foreground hover:bg-primary",
                  )}
                  onClick={() => {
                    setHour(h);
                    commit(h, minute);
                  }}
                >
                  {String(h).padStart(2, "0")}
                </button>
              ))}
            </div>
          </div>
          <div className="space-y-1">
            <p className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">Minute</p>
            <div className="h-40 overflow-y-auto rounded-md border border-border/60">
              {Array.from({ length: 60 }, (_, m) => (
                <button
                  key={m}
                  type="button"
                  className={cn(
                    "flex w-full items-center justify-center px-2 py-1.5 text-sm tabular-nums hover:bg-muted",
                    minute === m && "bg-primary text-primary-foreground hover:bg-primary",
                  )}
                  onClick={() => {
                    setMinute(m);
                    commit(hour, m);
                  }}
                >
                  {String(m).padStart(2, "0")}
                </button>
              ))}
            </div>
          </div>
        </div>
        <div className="flex items-center justify-between border-t px-3 py-2">
          <button
            type="button"
            className="text-primary text-sm hover:underline"
            onClick={() => {
              onChange?.("");
              setOpen(false);
            }}
          >
            Clear
          </button>
          <button
            type="button"
            className="text-primary text-sm hover:underline"
            onClick={() => {
              const h = now.getHours();
              const m = now.getMinutes();
              setHour(h);
              setMinute(m);
              commit(h, m);
              setOpen(false);
            }}
          >
            Now
          </button>
        </div>
      </PopoverContent>
    </Popover>
  );
}

function parseMonthValue(value?: string): Date | undefined {
  if (!value?.trim()) return undefined;
  const parsed = parse(`${value}-01`, "yyyy-MM-dd", new Date());
  return isValid(parsed) ? parsed : undefined;
}

interface MonthPickerProps {
  value?: string;
  onChange?: (value: string) => void;
  placeholder?: string;
  className?: string;
  align?: "start" | "center" | "end";
  id?: string;
  "aria-invalid"?: boolean;
}

/** Month/year picker — same popover pattern as DatePicker, month-grid selection (yyyy-MM). */
export function MonthPicker({
  value,
  onChange,
  placeholder = "Select month",
  className,
  align = "start",
  id,
  "aria-invalid": ariaInvalid,
}: MonthPickerProps) {
  const [open, setOpen] = React.useState(false);
  const selected = parseMonthValue(value);
  const now = new Date();
  const [viewYear, setViewYear] = React.useState(() => selected?.getFullYear() ?? now.getFullYear());

  React.useEffect(() => {
    if (selected) setViewYear(selected.getFullYear());
  }, [selected]);

  const label = selected ? format(selected, "MMMM yyyy") : placeholder;
  const selectedMonth = selected?.getMonth();
  const selectedYear = selected?.getFullYear();

  return (
    <Popover
      open={open}
      onOpenChange={(next) => {
        setOpen(next);
        if (next) setViewYear(selected?.getFullYear() ?? now.getFullYear());
      }}
    >
      <PopoverTrigger asChild>
        <Button
          type="button"
          variant="outline"
          id={id}
          aria-invalid={ariaInvalid}
          className={cn("h-8 w-full gap-2 font-normal", className)}
        >
          <span className={cn("min-w-0 flex-1 truncate text-left", !selected && "text-muted-foreground")}>
            {label}
          </span>
          <CalendarIcon className="size-3.5 shrink-0 text-muted-foreground" />
        </Button>
      </PopoverTrigger>
      <PopoverContent className="w-[280px] overflow-hidden p-0" align={align}>
        <div className="flex items-center justify-between border-b bg-muted/40 px-2 py-1.5">
          <Button
            type="button"
            variant="ghost"
            size="icon"
            className="size-7"
            onClick={() => setViewYear((y) => y - 1)}
            aria-label="Previous year"
          >
            <ChevronLeftIcon className="size-4" />
          </Button>
          <span className="text-sm font-medium tabular-nums">{viewYear}</span>
          <Button
            type="button"
            variant="ghost"
            size="icon"
            className="size-7"
            onClick={() => setViewYear((y) => y + 1)}
            aria-label="Next year"
          >
            <ChevronRightIcon className="size-4" />
          </Button>
        </div>
        <div className="grid grid-cols-4 gap-1 p-2">
          {MONTH_SHORT.map((name, monthIndex) => {
            const isSelected = selectedMonth === monthIndex && selectedYear === viewYear;
            return (
              <Button
                key={name}
                type="button"
                variant={isSelected ? "default" : "ghost"}
                size="sm"
                className="h-9 font-normal"
                onClick={() => {
                  onChange?.(format(new Date(viewYear, monthIndex, 1), "yyyy-MM"));
                  setOpen(false);
                }}
              >
                {name}
              </Button>
            );
          })}
        </div>
        <div className="flex items-center justify-between border-t px-3 py-2">
          <button
            type="button"
            className="text-primary text-sm hover:underline"
            onClick={() => {
              onChange?.("");
              setOpen(false);
            }}
          >
            Clear
          </button>
          <button
            type="button"
            className="text-primary text-sm hover:underline"
            onClick={() => {
              onChange?.(format(now, "yyyy-MM"));
              setViewYear(now.getFullYear());
              setOpen(false);
            }}
          >
            This month
          </button>
        </div>
      </PopoverContent>
    </Popover>
  );
}
