import { Input, InputProps } from "@nextui-org/react";
import { ControllerFieldState } from "react-hook-form";
import { FaEye, FaEyeSlash } from "react-icons/fa6";
import { useState } from "react";

import {
  PASSWORD_INPUT_MAX_LENGTH,
  PASSWORD_INPUT_MIN_LENGTH,
} from "@/constants/signup-form-constants";
import { AUTOCOMPLETE_VALUES } from "@/constants/signup-auto-complete-mapping";
import { validatePassword } from "@/utils/validatePassword";

type InputFormProps = {
  fieldProps: any;
  fieldState: ControllerFieldState;
  showGuidelines?: boolean;
  forceDarkMode?: boolean;
  control?: any;
  name?: string;
};

type InputComponentProps = InputProps & InputFormProps;

function PasswordInput({
  children,
  variant = "faded",
  color,
  size,
  value,
  defaultValue,
  placeholder,
  description,
  startContent,
  fullWidth,
  isClearable,
  isRequired = true,
  isReadOnly,
  isDisabled,
  isInvalid,
  baseRef,
  label,
  labelPlacement = "outside",
  disableAnimation,
  showGuidelines = true,
  fieldProps,
  fieldState,
  forceDarkMode = false,
  classNames = {
    base: forceDarkMode ? "dark:text-white" : "text-black",
    label: `block text-sm font-bold tracking-tight font-inter text-pretty ${
      forceDarkMode ? "dark:text-white" : ""
    }`,
    inputWrapper: "",
    innerWrapper: "",
    mainWrapper: "",
    input: `font-noto ${
      fieldState.invalid || isInvalid
        ? forceDarkMode
          ? "dark:text-white"
          : "text-black"
        : forceDarkMode
        ? "dark:text-white"
        : ""
    }`,
    clearButton: forceDarkMode
      ? "text-gray-400 hover:text-gray-300 dark:text-gray-400 dark:hover:text-gray-300"
      : "text-black hover:text-black/80",
    helperWrapper: "",
    description: `font-inter font-regular mt-0.5 text-[12px] leading-tight ${
      forceDarkMode ? "text-gray-400 dark:text-gray-400" : "text-gray-500"
    }`,
  },
  autoComplete = AUTOCOMPLETE_VALUES.NEW_PASSWORD,
  onChange,
  onValueChange,
  onClear,
}: InputComponentProps) {
  const [errors, setErrors] = useState({});
  const [isVisible, setIsVisible] = useState(false);
  const [fieldValue, setFieldValue] = useState(fieldProps.value ?? "");

  const toggleVisibility = () => {
    setIsVisible(!isVisible);
  };

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const inputValue = e.target.value;
    validatePassword(inputValue);
    setErrors(validatePassword(inputValue).errors);
    setFieldValue(e.target.value);
    fieldProps.onChange(e.target.value);
  };

  return (
    <>
      <Input
        {...fieldProps}
        autoComplete={autoComplete}
        baseRef={baseRef}
        classNames={classNames}
        color={color}
        defaultValue={defaultValue}
        description={description}
        disableAnimation={disableAnimation}
        endContent={
          <button
            className="focus:outline-none flex justify-center items-center my-auto size-4 me-1"
            type="button"
            onClick={toggleVisibility}
          >
            {isVisible ? (
              <FaEyeSlash aria-label="Hide password" tabIndex={0} />
            ) : (
              <FaEye aria-label="Show password" tabIndex={0} />
            )}
          </button>
        }
        fullWidth={fullWidth}
        id={fieldProps?.name}
        isClearable={isClearable}
        isDisabled={isDisabled}
        isInvalid={fieldState.invalid ?? isInvalid}
        isReadOnly={isReadOnly}
        isRequired={isRequired}
        label={label}
        labelPlacement={labelPlacement}
        maxLength={PASSWORD_INPUT_MAX_LENGTH}
        minLength={PASSWORD_INPUT_MIN_LENGTH}
        placeholder={placeholder}
        radius="sm"
        size={size}
        startContent={startContent}
        type={isVisible ? "text" : "password"}
        value={fieldValue ?? value}
        variant={variant}
        onChange={onChange ?? handleChange}
        onClear={onClear}
        onValueChange={onValueChange}
      >
        {children}
      </Input>
      {showGuidelines && (
        <div
          className={`mt-2 text-xs text-gray-500 ${
            forceDarkMode ? "dark:text-gray-300" : ""
          } font-inter`}
        >
          Password must meet the following criteria:
          <span className="space-y-0.5">
            {[
              { key: "length", label: "Minimum of 8 characters" },
              { key: "uppercase", label: "At least one uppercase letter" },
              { key: "lowercase", label: "At least one lowercase letter" },
              { key: "numeric", label: "At least one number" },
            ].map(({ key, label }) => (
              <div key={key} className="mt-2">
                • {label}{" "}
                <span
                  aria-label={`${label}: ${
                    errors[key as keyof typeof errors] ? "Met" : "Not met"
                  }`}
                  className={`${
                    errors[key as keyof typeof errors]
                      ? "text-green-800 font-bold"
                      : "text-red-800 font-bold"
                  }`}
                >
                  {errors[key as keyof typeof errors] ? "✓" : "✗"}
                </span>
              </div>
            ))}
          </span>
        </div>
      )}
    </>
  );
}

export default PasswordInput;
