import React, { forwardRef, type InputHTMLAttributes } from "react";
import cn from "classnames";

const classes = {
  root: "px-4 h-12 flex items-center w-full rounded border-gray-200 appearance-none transition duration-300 ease-in-out text-heading text-sm focus:outline-none focus:ring-0",
  normal:
    "bg-gray-100 border border-border-base focus:shadow focus:bg-light focus:border-gray-400",
  solid:
    "bg-gray-100 border border-border-100 focus:bg-light focus:border-gray-400",
  outline: "border border-border-base focus:border-gray-400",
  shadow: "focus:shadow",
};

type Variant = "normal" | "solid" | "outline";

interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
  label?: string;
  note?: string;
  error?: string;
  variant?: Variant;
  shadow?: boolean;
  inputClassName?: string;
  isRequired?: boolean;
  labelClass?: string;
  children?: React.ReactNode;
}

const Input = forwardRef<HTMLInputElement, InputProps>(
  (
    {
      className,
      label,
      note,
      name,
      error,
      children,
      variant = "normal",
      shadow = false,
      type = "text",
      inputClassName,
      isRequired = false,
      labelClass = "dark:text-white",
      ...rest
    },
    ref
  ) => {
    const rootClassName = cn(
      classes.root,
      {
        [classes.normal]: variant === "normal",
        [classes.solid]: variant === "solid",
        [classes.outline]: variant === "outline",
      },
      {
        [classes.shadow]: shadow,
      },
      inputClassName
    );

    return (
      <div className={`${className ?? ""} mb-0 md:mb-4`}>
        {label && (
          <label
            htmlFor={name}
            className={`block text-body-dark font-medium text-sm leading-none mb-3 ${labelClass}`}
          >
            {label}
            {isRequired && <i className="text-red-500">*</i>}
          </label>
        )}
        <input
          id={name}
          name={name}
          type={type}
          ref={ref}
          className={rootClassName}
          autoComplete="off"
          autoCorrect="off"
          autoCapitalize="off"
          spellCheck={false}
          aria-invalid={error ? "true" : "false"}
          {...rest}
        />
        {note && <p className="mt-2 text-xs text-body">{note}</p>}
        {error && (
          <p className="my-2 text-xs text-start text-red-500">{error}</p>
        )}
        {children}
      </div>
    );
  }
);

Input.displayName = "Input";

export default Input;
