"use client";
import { CalendarIcon } from "@/assets/icons";
import { cn } from "@/lib/utils";
import {
  Control,
  Controller,
  FieldValues,
  Path,
  RegisterOptions,
} from "react-hook-form";
import MultiDatePicker, { DateObject } from "react-multi-date-picker";
import TimePicker from "react-multi-date-picker/plugins/time_picker";

interface IProps<T extends FieldValues> {
  control: Control<T>;
  name: Path<T>;
  label: string;
  placeholder?: string;
  required?: boolean;
  multiple?: boolean;
  range?: boolean;
  onlyMonthPicker?: boolean;
  onlyYearPicker?: boolean;
  minDate?: number;
  maxDate?: number;
  timePicker?: boolean;
  clearable?: boolean;
  rules?: Omit<
    RegisterOptions<T, Path<T>>,
    "valueAsNumber" | "valueAsDate" | "setValueAs" | "disabled"
  >;
}

const DatePicker = <T extends FieldValues>({
  control,
  name,
  label,
  multiple = false,
  placeholder,
  required,
  range = false,
  timePicker = false,
  onlyMonthPicker = false,
  onlyYearPicker = false,
  rules,
  maxDate,
  minDate,
  clearable = false,
}: IProps<T>) => {
  return (
    <div className="space-y-3">
      <label
        htmlFor={name}
        className="block text-body-sm font-semibold capitalize tracking-[0.01em] text-dark dark:text-white"
      >
        {label}
        {required && <span className="ml-1 select-none text-error">*</span>}
      </label>

      <div>
        <Controller
          control={control}
          name={name}
          rules={rules}
          render={({
            field: { onChange, name, value },
            formState: { errors },
          }) => {
            const error = errors[name];

            const toUnixSeconds = (v: unknown): number | null => {
              if (v === "" || v === undefined || v === null) return null;
              const n = typeof v === "number" ? v : Number(v);
              return Number.isFinite(n) ? n : null;
            };

            const toPickerValue = ():
              | DateObject
              | DateObject[]
              | undefined => {
              if (value === "" || value === undefined || value === null) {
                return undefined;
              }

              if (multiple && Array.isArray(value)) {
                const secs = value
                  .map(toUnixSeconds)
                  .filter((s): s is number => s !== null);
                if (!secs.length) return undefined;
                return secs.map((unix) => new DateObject(new Date(unix * 1000)));
              }

              if (range && Array.isArray(value)) {
                const secs = value
                  .map(toUnixSeconds)
                  .filter((s): s is number => s !== null);
                if (!secs.length) return undefined;
                return secs.map((unix) => new DateObject(new Date(unix * 1000)));
              }

              if (range && !Array.isArray(value)) {
                return undefined;
              }

              const unix = toUnixSeconds(value);
              if (unix === null) return undefined;
              return new DateObject(new Date(unix * 1000));
            };

            const pickerValue = toPickerValue();
            const hasValue =
              pickerValue !== undefined &&
              (Array.isArray(pickerValue) ? pickerValue.length > 0 : true);

            return (
              <>
                <div className="relative">
                  <MultiDatePicker
                    range={range}
                    minDate={minDate}
                    maxDate={maxDate}
                    onlyMonthPicker={onlyMonthPicker}
                    plugins={
                      timePicker
                        ? [<TimePicker key={name} position="bottom" />]
                        : []
                    }
                    onlyYearPicker={onlyYearPicker}
                    multiple={multiple}
                    value={pickerValue}
                    onChange={(date: DateObject | DateObject[] | null) => {
                      if (!date) {
                        onChange("");
                        return;
                      }

                      if (Array.isArray(date)) {
                        const unixTimestamps = date.map((d) => d.toUnix());
                        onChange(unixTimestamps);
                      } else if (date instanceof DateObject) {
                        onChange(date.isValid ? date.toUnix() : "");
                      }
                    }}
                    format={`YYYY/MM/DD ${timePicker ? "HH:mm" : ""}`}
                    containerClassName="w-full"
                    inputClass={cn(
                      "w-full rounded-xl border border-stroke/70 bg-white/90 px-5.5 py-3 pl-12.5 text-dark shadow-[0_1px_2px_rgba(16,24,40,0.04),0_8px_20px_rgba(16,24,40,0.04)] outline-none backdrop-blur-[1px] transition-all duration-200 focus:border-primary/70 focus:bg-white focus:shadow-[0_0_0_2px_rgba(59,130,246,0.14),0_10px_24px_rgba(59,130,246,0.08)] disabled:cursor-default disabled:bg-gray-2/70 dark:border-dark-3/80 dark:bg-dark-2/85 dark:text-white dark:focus:border-primary/80 dark:focus:shadow-[0_0_0_2px_rgba(59,130,246,0.2),0_10px_24px_rgba(15,23,42,0.45)] dark:disabled:bg-dark",
                      clearable && hasValue && "pr-11",
                      error &&
                        "border-red/80 focus:border-red focus:shadow-[0_0_0_2px_rgba(239,68,68,0.16),0_10px_24px_rgba(239,68,68,0.1)] dark:border-red/80 dark:focus:shadow-[0_0_0_2px_rgba(239,68,68,0.24),0_10px_24px_rgba(127,29,29,0.45)]",
                    )}
                    placeholder={placeholder}
                  />
                  <span className="pointer-events-none absolute left-4.5 top-1/2 -translate-y-1/2 text-dark-5 transition-colors dark:text-dark-6">
                    <CalendarIcon />
                  </span>
                  {clearable && hasValue && (
                    <button
                      type="button"
                      aria-label="Clear date"
                      className="absolute right-3 top-1/2 z-10 -translate-y-1/2 rounded-md p-1 text-dark-5 transition hover:bg-gray-2 hover:text-dark dark:text-dark-6 dark:hover:bg-dark-3 dark:hover:text-white"
                      onClick={(e) => {
                        e.preventDefault();
                        e.stopPropagation();
                        onChange("");
                      }}
                    >
                      <svg
                        width="16"
                        height="16"
                        viewBox="0 0 16 16"
                        fill="none"
                        xmlns="http://www.w3.org/2000/svg"
                        aria-hidden
                      >
                        <path
                          d="M12 4L4 12M4 4L12 12"
                          stroke="currentColor"
                          strokeWidth="2"
                          strokeLinecap="round"
                          strokeLinejoin="round"
                        />
                      </svg>
                    </button>
                  )}
                </div>

                {error && (
                  <p className="mt-1.5 text-sm font-medium text-error">
                    {error.message as string}
                  </p>
                )}
              </>
            );
          }}
        />
      </div>
    </div>
  );
};

export default DatePicker;
