"use client";

import { Input, SlotsToClasses } from "@heroui/react";
import {
  ForwardedRef,
  ReactNode,
  forwardRef,
  useImperativeHandle,
  useRef,
} from "react";
import { ControllerFieldState, ControllerRenderProps } from "react-hook-form";

type CustomInputProps = {
  field: Partial<ControllerRenderProps<any, any>> & {
    name: string;
    value?: any;
    onChange: (value: any) => void;
  };
  fieldState?: ControllerFieldState;
  type?: string;
  label?: string;
  variant?: "flat" | "faded" | "bordered" | "underlined";
  size?: "md" | "sm" | "lg";
  disabled?: boolean;
  placeholder?: string;
  className?: string;
  classNames?: SlotsToClasses<
    | "label"
    | "input"
    | "base"
    | "description"
    | "errorMessage"
    | "mainWrapper"
    | "inputWrapper"
    | "innerWrapper"
    | "clearButton"
    | "helperWrapper"
  >;
  inputMode?:
    | "search"
    | "text"
    | "email"
    | "tel"
    | "url"
    | "none"
    | "numeric"
    | "decimal";
  startContent?: ReactNode;
  endContent?: ReactNode;
  value?: string;
  onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
  onFocus?: () => void;
  onBlur?: () => void;
  onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
  min?: string | number;
  max?: string | number;
  errorMessage?: string;
};

export const CustomInput = forwardRef(
  (
    {
      field,
      fieldState,
      type,
      label,
      variant = "bordered",
      size = "sm",
      disabled,
      placeholder,
      className,
      classNames,
      inputMode,
      startContent,
      endContent,
    }: CustomInputProps,
    ref: ForwardedRef<HTMLInputElement>,
  ) => {
    const internalRef = useRef<HTMLInputElement>(null);

    useImperativeHandle(ref, () => internalRef.current as HTMLInputElement);

    const isInvalid = !!fieldState?.error;
    const errorMessage = fieldState?.error?.message || "";

    const inputWrapperSize =
      size === "sm" ? "h-11" : size === "md" ? "h-12" : "h-14";

    const labelSize = size === "sm" ? "text-xs py-1" : "text-sm py-2";

    return (
      <>
        <div className={`flex flex-col w-full ${className}`}>
          <Input
            type={type}
            label={label}
            labelPlacement="outside-top"
            placeholder={placeholder}
            size={size}
            radius="sm"
            fullWidth
            variant={variant}
            color={isInvalid ? "danger" : "primary"}
            errorMessage={errorMessage}
            isInvalid={isInvalid}
            disabled={disabled}
            className={className}
            classNames={{
              label: `text-primaryText font-medium ${labelSize}`,
              input:
                "bg-transparent !rounded-lg text-sm placeholder:text-primaryText focus:outline-none px-3",
              inputWrapper: `border rounded-xl border-borderClr focus-within:ring-1 ${inputWrapperSize} ${
                isInvalid ? "ring-red-500" : "focus-within:ring-primary"
              }`,
              errorMessage: "text-xs mt-1 px-1 text-red-500",
              ...classNames,
            }}
            inputMode={inputMode}
            startContent={startContent}
            endContent={endContent}
            {...(field ?? {
              value: "",
              onChange: () => {},
              onFocus: () => {},
              onBlur: () => {},
              onKeyDown: () => {},
              ref: internalRef,
            })}
          />
        </div>
      </>
    );
  },
);
CustomInput.displayName = "CustomInput";
