"use client";

import {
  FocusEventHandler,
  forwardRef,
  ForwardRefRenderFunction,
  MouseEventHandler,
  useCallback,
  useState,
} from "react";
import { InputFieldProps, InputProps } from "./types";

import { MaterialIcon } from "@shared/components/material-icon";
import { Text } from "@shared/components/text";
import { cx } from "@shared/utils";

export const InputField: ForwardRefRenderFunction<
  HTMLInputElement,
  InputFieldProps
> = (props, ref) => {
  const {
    className,
    size,
    required,
    placeholder,
    label,
    state,
    errorText,
    prefixIconName,
    prefixIconFill = true,
    suffixIconFill = false,
    prefixIconSize = 24,
    suffixIconName,
    suffixIconSize = 24,
    containerClassName,
    prefixIconClassName,
    loading,
    hasError,
    type,
    // Filter out all non-DOM props
    ...rest
  } = props;

  // Use hasError to override state if provided
  const effectiveState = hasError ? "error" : state;

  const sizeClasses = {
    sm: "h-[48px] px-3 py-2",
    slim: "h-12",
    medium: "h-14",
    large: "h-[60px]",
  };

  const [isHovered, setIsHovered] = useState(false);
  const [isFocused, setIsFocused] = useState(false);
  const [inputType, setInputType] = useState(type || "text");

  const handleMouseOver = () => setIsHovered(true);
  const handleMouseOut = () => setIsHovered(false);
  const handleFocus: FocusEventHandler<HTMLInputElement> = e => {
    rest.onFocus?.(e);
    setIsFocused(true);
  };
  const handleBlur: FocusEventHandler<HTMLInputElement> = e => {
    rest.onBlur?.(e);
    setIsFocused(false);
  };

  const togglePasswordVisibility = useCallback<
    MouseEventHandler<HTMLDivElement>
  >(e => {
    e.stopPropagation();
    setInputType(prevType => (prevType === "password" ? "text" : "password"));
  }, []);

  return (
    <div className="relative">
      {label ? (
        <label htmlFor={label} className={cx("inline-block pb-1")}>
          <Text as="span" className="footnote text-text">
            {label}
            {required ? (
              <span className="pl-1 text-text-critical">*</span>
            ) : null}
          </Text>
        </label>
      ) : null}

      <div
        className={cx(
          "relative flex flex-row items-center overflow-hidden rounded-input border border-input-border bg-input-bg-surface",
          sizeClasses[size || "medium"],
          containerClassName,
          (isHovered || effectiveState === "hover") &&
            !isFocused &&
            effectiveState !== "error" &&
            "border-input-border-hover",
          (isFocused ||
            effectiveState === "focus" ||
            effectiveState === "active") &&
            "border-input-border-selected outline outline-1 outline-input-border-selected",
          effectiveState === "error" &&
            "border-input-border-critical outline outline-1 outline-input-border-critical"
        )}
      >
        {prefixIconName ? (
          <div
            className="mr-1"
            style={{
              width: prefixIconSize,
              height: prefixIconSize,
              overflow: "hidden",
            }}
          >
            <MaterialIcon
              name={prefixIconName}
              fill={prefixIconFill ? 1 : 0}
              size={prefixIconSize}
              className={cx(prefixIconClassName)}
            />
          </div>
        ) : null}
        <input
          ref={ref}
          id={label}
          disabled={loading || rest.disabled}
          className={cx(
            "h-full grow rounded-input p-4 caret-bg-inverse placeholder:text-input-text-placeholder focus:border-none focus:outline-none",
            "text-body2",
            size === "slim" && "text-body3",
            className
          )}
          placeholder={placeholder}
          type={inputType}
          {...rest}
          onMouseOver={handleMouseOver}
          onMouseOut={handleMouseOut}
          onFocus={handleFocus}
          onBlur={handleBlur}
        />
        {suffixIconName ? (
          <div
            className="ml-2"
            style={{
              width: suffixIconSize,
              height: suffixIconSize,
              overflow: "hidden",
            }}
            onClick={togglePasswordVisibility}
          >
            <MaterialIcon
              name={inputType === "text" ? "visibility" : "visibility_off"}
              size={suffixIconSize}
              fill={suffixIconFill ? 1 : 0}
            />
          </div>
        ) : null}
      </div>
      {effectiveState === "error" && errorText && errorText != "" ? (
        <Text
          className={cx(
            "footnote left-0 top-full inline-flex items-center pt-1 text-text-critical"
          )}
        >
          <MaterialIcon name="info" size={20} className="mr-1" />
          {errorText || "Error"}
        </Text>
      ) : null}
    </div>
  );
};

export const Input = forwardRef<HTMLInputElement, InputFieldProps>(InputField);

Input.displayName = "Input";

export type { InputFieldProps, InputProps };
