import * as React from "react";
import { format, parse } from "date-fns";
import { ptBR } from "date-fns/locale";
import { DateRange } from "react-day-picker";
import { Calendar as CalendarIcon, X } from "lucide-react";
import { useControllableState } from "@radix-ui/react-use-controllable-state";
import { cn } from "@/lib/utils"; // se não tiver, é o util padrão do shadcn
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Popover,
  PopoverTrigger,
  PopoverContent,
} from "@/components/ui/popover";
import { Calendar } from "@/components/ui/calendar";

type Props = {
  value?: DateRange | string;
  onChange?: (range: DateRange | undefined) => void;
  numberOfMonths?: number;
  inputFormat?: string;
  placeholder?: string;
  className?: string;
  label?: string;
};

export function DateRangePicker({
  value,
  onChange,
  numberOfMonths = 2,
  inputFormat = "dd/MM/yyyy",
  placeholder = "dd/mm/aaaa",
  className,
  label = "Selecione o período",
}: Props) {
  const [open, setOpen] = React.useState(false);
  const [quickFilterSelected, setQuickFilterSelected] = React.useState(
    value === "*" ? "todos" : ""
  );

  const [range, setRange] = useControllableState<DateRange | any | undefined>({
    prop: value,
    defaultProp: undefined,
    onChange,
  });

  function clear() {
    setRange("*");
    setQuickFilterSelected("todos");
  }

  function applyQuickFilter(filter: string) {
    const now = new Date();
    setQuickFilterSelected(filter);
    switch (filter) {
      case "todos":
        // aqui você pode só "resetar" e tratar no onChange
        setRange("*");
        onChange?.("*" as any);
        break;

      case "dia":
        setRange({
          from: new Date(now.setHours(0, 0, 0, 0)),
          to: new Date(now.setHours(23, 59, 59, 999)),
        });
        break;

      case "semana": {
        const start = new Date(now);
        start.setDate(now.getDate() - now.getDay() + 1); // segunda
        const end = new Date(start);
        end.setDate(start.getDate() + 6); // domingo
        setRange({ from: start, to: end });
        break;
      }

      case "mes": {
        const start = new Date(now.getFullYear(), now.getMonth(), 1);
        const end = new Date(now.getFullYear(), now.getMonth() + 1, 0);
        setRange({ from: start, to: end });
        break;
      }
      case "semestre": {
        const year = now.getFullYear();
        const month = now.getMonth(); // 0-11
        const firstSemester = month <= 5; // Jan-Jun
        const start = firstSemester
          ? new Date(year, 0, 1) // 01/01
          : new Date(year, 6, 1); // 01/07
        const end = firstSemester
          ? new Date(year, 6, 0) // 30/06
          : new Date(year, 12, 0); // 31/12
        setRange({ from: start, to: end });
        break;
      }

      case "ano": {
        const year = now.getFullYear();
        const start = new Date(year, 0, 1); // 01/01
        const end = new Date(year, 12, 0); // 31/12
        setRange({ from: start, to: end });
        break;
      }
    }
  }

  function handleSelect(next: DateRange | undefined) {
    setQuickFilterSelected("");
    setRange(next);
  }

  function parseInput(text: string) {
    const d = parse(text, inputFormat, new Date());
    return isNaN(d.getTime()) ? undefined : d;
  }

  function handleStartChange(e: React.ChangeEvent<HTMLInputElement>) {
    const d = parseInput(e.target.value);
    if (!d) return;
    setQuickFilterSelected("");
    if (range?.to && d > range.to) setRange({ from: d, to: undefined });
    else setRange({ from: d, to: range?.to });
  }

  function handleEndChange(e: React.ChangeEvent<HTMLInputElement>) {
    const d = parseInput(e.target.value);
    if (!d) return;
    setQuickFilterSelected("");
    if (range?.from && d < range.from) setRange({ from: d, to: undefined });
    else setRange({ from: range?.from, to: d });
  }

  const display = React.useMemo(() => {
    if (range === "*") return "Todos";
    if (!range?.from && !range?.to) return "Selecionar datas";
    const s = range?.from
      ? format(range.from, inputFormat, { locale: ptBR })
      : "";
    const e = range?.to ? format(range.to, inputFormat, { locale: ptBR }) : "";
    return s && e ? `${s} → ${e}` : s || e;
  }, [range, inputFormat]);

  return (
    <div className={cn("inline-block", className)}>
      <Popover open={open} onOpenChange={setOpen}>
        <PopoverTrigger asChild>
          <Button
            variant="outline"
            className="inline-flex items-center gap-2 rounded-lg"
          >
            <CalendarIcon className="h-4 w-4 text-muted-foreground" />
            <span className="text-muted-foreground">Período:</span>
            <span className="truncate max-w-[220px] font-semibold text-black">
              {display}
            </span>
          </Button>
        </PopoverTrigger>

        <PopoverContent align="start" className="w-[630px] max-w-[92vw] p-4">
          <div className="mb-2 flex items-center justify-between">
            <span className="font-semibold">{label}</span>
            <button
              type="button"
              onClick={clear}
              className="text-destructive text-sm hover:underline"
            >
              Delete
            </button>
          </div>

          <div className="mb-3 flex items-center justify-around gap-2">
            <ClearableInput
              value={
                range?.from
                  ? format(range.from, inputFormat, { locale: ptBR })
                  : ""
              }
              onChange={handleStartChange}
              placeholder={placeholder}
              ariaLabel="Data inicial"
              onClear={() => {
                setQuickFilterSelected("");
                setRange({ from: undefined, to: range?.to });
              }}
            />
            <span className="text-muted-foreground select-none">—</span>
            <ClearableInput
              value={
                range?.to ? format(range.to, inputFormat, { locale: ptBR }) : ""
              }
              onChange={handleEndChange}
              placeholder={placeholder}
              ariaLabel="Data final"
              onClear={() => {
                setQuickFilterSelected("");
                setRange({ from: undefined, to: range?.to });
              }}
            />
          </div>
          <div className="flex gap-3 mb-2 items-center">
            <p className="text-sm">Filtros rápidos: </p>
            {["todos", "dia", "semana", "mes", "semestre", "ano"].map((d) => (
              <div
                key={d}
                onClick={() => applyQuickFilter(d)}
                className={`rounded-full cursor-pointer p-1 px-3 text-sm border border-stroke capitalize ${quickFilterSelected === d ? "bg-primary text-white" : ""}`}
              >
                {d}
              </div>
            ))}
          </div>

          <Calendar
            mode="range"
            selected={range}
            onSelect={handleSelect}
            numberOfMonths={numberOfMonths}
            weekStartsOn={1}
            locale={ptBR}
            modifiersClassNames={{
              range_start:
                "bg-primary !rounded-tl-[10px]  !rounded-tr-[0px] !rounded-br-[0px] !rounded-bl-[10px] text-primary-foreground hover:bg-primary focus:bg-primary",
              range_end:
                "bg-primary text-primary-foreground !rounded-tl-[0px]  !rounded-tr-[10px] !rounded-br-[10px] !rounded-bl-[0px] hover:bg-primary focus:bg-primary",
              range_middle: "bg-stroke rounded-none text-foreground",
            }}
            className="rounded-md border justify-around"
            classNames={{
              months:
                "flex flex-col sm:flex-row space-y-4 justify-around sm:space-y-0",
            }}
          />
        </PopoverContent>
      </Popover>
    </div>
  );
}
function ClearableInput(props: {
  value: string;
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
  placeholder?: string;
  ariaLabel?: string;
  onClear?: () => void;
}) {
  const { value, onChange, placeholder, ariaLabel, onClear } = props;
  return (
    <div className="relative flex-1">
      <Input
        value={value}
        onChange={onChange}
        placeholder={placeholder}
        aria-label={ariaLabel}
        className="pr-9 font-semibold"
      />
      {value ? (
        <button
          type="button"
          onClick={onClear}
          className="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground"
          aria-label="Limpar data"
        >
          <X className="h-4 w-4" />
        </button>
      ) : null}
    </div>
  );
}
