import {
  useState,
  KeyboardEvent,
  useEffect,
  HTMLAttributes,
  ReactElement,
} from "react";
import { RegisterOptions, useFormContext } from "react-hook-form";
import { isNullOrWhiteSpace } from "../../../util/stringUtil";

export type InternalInputProps = {
  inputClassName?: string;
  inputState: "default" | "active" | "error" | "disabled";
  id: string;
  name: string;
  label: string;
  disabled?: boolean;
  registerWhenDisabled?: boolean;
  iconLeft?: ReactElement;
  onClickIcon?: () => void;
  iconRight?: ReactElement;
  type: React.HTMLInputTypeAttribute;
  autoComplete?: string;
  registerOptions?: RegisterOptions;
  updateFilteredOptions?: (currentInput: string) => void;
  setAutocompleteListActive?: (isListActive: boolean) => void;
  handleKeyPressed?: (event: KeyboardEvent<HTMLInputElement>) => void;
  setHasFocus: React.Dispatch<React.SetStateAction<boolean>>;
  isActive: boolean;
  setIsActive: React.Dispatch<React.SetStateAction<boolean>>;
  inputMode?: HTMLAttributes<HTMLInputElement>["inputMode"];
  readonly?: boolean;
  selectOnFocus?: boolean;
};

export default function InternalInput({
  inputClassName,
  inputState,
  id,
  name,
  label,
  registerWhenDisabled,
  iconLeft,
  onClickIcon,
  iconRight,
  type,
  disabled = false,
  autoComplete,
  registerOptions,
  readonly,
  selectOnFocus,
  updateFilteredOptions,
  handleKeyPressed,
  setAutocompleteListActive,
  setHasFocus,
  isActive,
  setIsActive,
  inputMode = "text",
}: InternalInputProps) {
  const { register, getValues } = useFormContext();

  const inputBaseClassName =
    "p-0 border-none w-full focus:ring-0 text-neutral-very-dark font-normal text-base peer placeholder-neutral-medium disabled:placeholder-neutral-medium-light disabled:text-neutral-medium-light";

  const [floatingClassName, setFloatingClassName] = useState(
    inputBaseClassName + (isActive ? " pt-5" : "")
  );

  const activateFloat = (useTransition: boolean) => {
    if (!floatingClassName.includes("pt-5")) {
      setFloatingClassName(
        `${floatingClassName}${useTransition ? " transition-all duration-200 ease-in-out" : ""} pt-5`
      );
      setIsActive(true);
    }
    if (setAutocompleteListActive !== undefined && useTransition) {
      setAutocompleteListActive(true);
    }
  };

  const deactiveFloat = () => {
    if (
      floatingClassName.includes("pt-5") &&
      isNullOrWhiteSpace(getValues(name))
    ) {
      setFloatingClassName(inputBaseClassName);
      setIsActive(false);
    }
    if (setAutocompleteListActive !== undefined) {
      setAutocompleteListActive(false);
    }
  };

  useEffect(() => {
    if (!isNullOrWhiteSpace(getValues(name))) {
      activateFloat(false);
    }
  }, [getValues(name)]);

  const shouldRegisterInput = registerWhenDisabled || !disabled;
  const registerReturn = shouldRegisterInput
    ? register(name, {
        ...registerOptions,
        onBlur: (event) => {
          if (registerOptions?.onBlur) {
            registerOptions.onBlur(event);
          }
          event.preventDefault();
          deactiveFloat();
          event.target.placeholder = label;
          setHasFocus(false);
        },
        onChange: (event) => {
          if (registerOptions?.onChange) {
            registerOptions.onChange(event);
          }
          activateFloat(true);
          if (updateFilteredOptions !== undefined) {
            updateFilteredOptions(event.target.value);
          }
        },
        setValueAs: (value) => {
          let newValue = value;
          if (registerOptions?.setValueAs) {
            newValue = registerOptions.setValueAs(value);
          }
          return newValue?.trim() ?? newValue;
        },
      })
    : null;

  return (
    <div className="px-2 xs:px-3 basis-full text-brand-primary flex gap-x-3 items-center py-1.5">
      <div
        className={`input-state-${inputState} ${disabled && "!fill-neutral-medium-light"} ${onClickIcon && "cursor-pointer"}`}
        onClick={onClickIcon}
      >
        {iconLeft}
      </div>
      <div className="relative ml-0 z-0 h-full w-full">
        <input
          {...registerReturn}
          type={type}
          name={name}
          id={id}
          disabled={disabled}
          placeholder={label}
          readOnly={readonly}
          autoComplete={autoComplete}
          inputMode={inputMode}
          className={`${floatingClassName} ${inputClassName} w-full focus:outline-none h-full`}
          onFocus={(event) => {
            activateFloat(true);
            event.target.placeholder = "";
            setHasFocus(true);
            if (selectOnFocus) {
              event.target.select();
            }
          }}
          onKeyDown={(event) => {
            if (handleKeyPressed !== undefined) {
              handleKeyPressed(event);
            }
          }}
        />
        <label
          className={`absolute top-0 text-left cursor-text left-0 transition-all duration-200 ease-in-out peer-disabled:text-neutral-medium-light text-xs font-bold mb-8 truncate w-full`}
          htmlFor={name}
          title={label}
        >
          {isActive ? label : null}
        </label>
      </div>
      <div
        className={`input-state-${inputState} ${disabled && "!fill-neutral-medium-light"}  ${onClickIcon && "cursor-pointer"}`}
        onClick={onClickIcon}
      >
        {iconRight}
      </div>
    </div>
  );
}
