import { zodResolver } from "@hookform/resolvers/zod";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useForm } from "react-hook-form";
import z from "zod";

import type { Route } from "next";
import { useEffect, type ChangeEvent } from "react";
import styles from "./DateRangeInput.module.scss";

const formSchema = z
  .object({
    startDate: z.string().nullish(),
    endDate: z.string().nullish(),
  })
  .refine(
    ({ startDate, endDate }) => {
      if (!startDate || !endDate) return true;
      return startDate <= endDate;
    },
    {
      message: "Start date must be before end date",
      path: ["startDate"],
    },
  );

export default function DateRangeInput({
  label,
  name,
}: {
  label?: string;
  name: string;
}) {
  const router = useRouter();
  const pathname = usePathname();
  const searchParamsReadonly = useSearchParams();

  const minSearchParamName = `min${name.at(0)?.toUpperCase() ?? ""}${name.slice(1)}`;
  const maxSearchParamName = `max${name.at(0)?.toUpperCase() ?? ""}${name.slice(1)}`;

  const minDate = searchParamsReadonly.get(minSearchParamName);
  const maxDate = searchParamsReadonly.get(maxSearchParamName);

  const {
    register,
    trigger,
    formState: { errors },
  } = useForm({
    resolver: zodResolver(formSchema),
    mode: "all",
    defaultValues: {
      startDate: minDate,
      endDate: maxDate,
    },
  });

  function handleSetDate(type: "min" | "max", value: string) {
    const searchParams = new URLSearchParams(searchParamsReadonly);

    searchParams.set(
      type === "min" ? minSearchParamName : maxSearchParamName,
      value,
    );

    router.replace(`${pathname}?${searchParams}` as Route);
  }

  useEffect(() => {
    void trigger();
  }, [minDate, maxDate, trigger]);

  return (
    <div className={styles["date-range-input"]}>
      {label && (
        <span className={styles["date-range-input__label"]}>{label}</span>
      )}

      <div className={styles["date-range-input__input-container"]}>
        <div className={styles["date-range-input__input-wrapper"]}>
          <input
            type="date"
            {...register("startDate", {
              onChange: (event: ChangeEvent<HTMLInputElement>) => {
                handleSetDate("min", event.target.value);
              },
            })}
            className={styles["date-range-input__input"]}
          />

          <input
            type="date"
            {...register("endDate", {
              onChange: (event: ChangeEvent<HTMLInputElement>) => {
                handleSetDate("max", event.target.value);
              },
            })}
            className={styles["date-range-input__input"]}
          />
        </div>

        {errors.startDate?.message && (
          <p className={styles["date-range-input__error-message"]}>
            {errors.startDate.message}
          </p>
        )}
      </div>
    </div>
  );
}
