import { cn } from "@/lib/utils";
import {
  HTMLInputAutoCompleteAttribute,
  type HTMLInputTypeAttribute,
  useId,
} from "react";
import {
  type FieldErrors,
  type FieldValues,
  type Path,
  type UseFormRegister,
  type UseFormRegisterReturn,
} from "react-hook-form";

type InputGroupProps<T extends FieldValues> = {
  name: Path<T>;
  label: string;
  type: HTMLInputTypeAttribute;
  placeholder: string;
  className?: string;
  fileStyleVariant?: "style1" | "style2";
  required?: boolean;
  disabled?: boolean;
  active?: boolean;
  handleChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
  value?: string;
  icon?: React.ReactNode;
  iconPosition?: "left" | "right";
  height?: "sm" | "default";
  autoComplete?: HTMLInputAutoCompleteAttribute;
  defaultValue?: string;
  register?: UseFormRegister<T>;
  errors?: FieldErrors<T>;
} & Partial<UseFormRegisterReturn>;

const InputGroup = <T extends FieldValues>({
  className,
  label,
  type,
  placeholder,
  required,
  disabled,
  active,
  handleChange,
  icon,
  name,
  register,
  errors,
  autoComplete,
  onChange,
  onBlur,
  ref,
  ...props
}: InputGroupProps<T>): React.ReactElement => {
  const id = useId();

  const error = errors && errors[name];

  return (
    <div className={className}>
      <label
        htmlFor={id}
        className="text-body-sm font-medium text-dark dark:text-white"
      >
        {label}
        {required && <span className="ml-1 select-none text-error">*</span>}
      </label>

      <div
        className={cn(
          "relative mt-3 [&_svg]:absolute [&_svg]:top-1/2 [&_svg]:-translate-y-1/2",
          props.iconPosition === "left"
            ? "[&_svg]:left-4.5"
            : "[&_svg]:right-4.5",
        )}
      >
        <input
          id={id}
          type={type}
          placeholder={placeholder}
          name={name}
          ref={ref}
          autoComplete={autoComplete}
          onChange={(e) => {
            onChange?.(e);
            handleChange?.(e);
          }}
          onBlur={onBlur}
          {...(!onChange &&
            props.value !== undefined && { value: props.value })}
          {...(!onChange &&
            props.defaultValue !== undefined && {
              defaultValue: props.defaultValue,
            })}
          className={cn(
            "w-full rounded-lg border-[1.5px] border-stroke bg-transparent outline-none transition focus:border-primary disabled:cursor-default disabled:bg-gray-2 data-[active=true]:border-primary dark:border-dark-3 dark:bg-dark-2 dark:focus:border-primary dark:disabled:bg-dark dark:data-[active=true]:border-primary",
            // Add error styles conditionally
            error && "border-red focus:border-red dark:border-red",
            type === "file"
              ? getFileStyles(props.fileStyleVariant!)
              : "px-5.5 py-3 text-dark placeholder:text-dark-6 dark:text-white",
            props.iconPosition === "left" && "pl-12.5",
            props.height === "sm" && "py-2.5",
          )}
          disabled={disabled}
          data-active={active}
        />

        {icon}
      </div>

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

export default InputGroup;

function getFileStyles(variant: "style1" | "style2") {
  switch (variant) {
    case "style1":
      return `file:mr-5 file:border-collapse file:cursor-pointer file:border-0 file:border-r file:border-solid file:border-stroke file:bg-[#E2E8F0] file:px-6.5 file:py-[13px] file:text-body-sm file:font-medium file:text-dark-5 file:hover:bg-primary file:hover:bg-opacity-10 dark:file:border-dark-3 dark:file:bg-white/30 dark:file:text-white`;
    default:
      return `file:mr-4 file:rounded file:border-[0.5px] file:border-stroke file:bg-stroke file:px-2.5 file:py-1 file:text-body-xs file:font-medium file:text-dark-5 file:focus:border-primary dark:file:border-dark-3 dark:file:bg-white/30 dark:file:text-white px-3 py-[9px]`;
  }
}
