"use client"
import type { DefaultHTMLStyleProps, Style } from "@/core/types/common";
import type { FocusEventHandler, ForwardedRef, MouseEvent, RefObject, ReactNode, ChangeEventHandler } from "react";

import { forwardRef, useCallback, useEffect, useRef, useState } from "react";

import SearchIcon from "@/core/components/Icons/SearchIcon";
import Image from "next/image";

type TextInputSize = "default" | "medium";

interface TextInputProps extends DefaultHTMLStyleProps, Style {
  value: string;
  name?: string;
  form?: string;
  placeholder?: string;
  onChange?: (value: string) => void;
  onClick?: (event: MouseEvent<HTMLDivElement>) => void;
  onClear?: () => void;
  search?: boolean;
  inputClassName?: string;
  size?: TextInputSize;
  icon?: ReactNode;
  iconSize?: { width: number, height: number, };
  iconSrc?: string;
  disabled?: boolean;
  required?: boolean;
}

export default forwardRef(
  /**
   * Shared `TextInput` component to handling the user's **Input** data.\
   * The text input component provides _**extended functionality**_ beside the custom styles.\
   * The `ref` props supported as well with `ForwardRef` interface.
   * @param onClear
   * @param onChange
   * @param required
   * @param {Readonly<TextInputProps} props - basic custom TextInput props interface – TextInputProps.
   * @param {React.ForwardedRef<HTMLInputElement>} ref - reference object.
   * @return {ReactNode} - ReactNode element.
   * @constructor
   */
  function TextInput(
      { onClear, onChange, required, ...props }: Readonly<TextInputProps>,
      ref: ForwardedRef<HTMLInputElement>
  ): ReactNode {
  const inputRef = useRef<HTMLInputElement>(null);
  const [focused, setFocused] = useState<boolean>(false);

  const sizes: Record<TextInputSize, number> = { default: 32, medium: 40, }

  const onChangeHandler = useCallback(
    (value: string) => onChange && onChange(value),
    [onChange]
  );

  const onInputText: ChangeEventHandler<HTMLInputElement> = useCallback(
    ({ target: { value } }) => onChangeHandler(value),
    [onChangeHandler]
  );
  const focusHandler: FocusEventHandler<HTMLInputElement> = useCallback(
    (event) => setFocused(true),
    []
  );
  const blurHandler: FocusEventHandler<HTMLInputElement> = useCallback(
    (event) => setFocused(false),
    []
  );

  const clear = useCallback(
    () => {
      onChangeHandler("");
      setFocused(false);
      onClear && onClear();
      if (inputRef.current) inputRef.current.blur();
    },
    [onChangeHandler, onClear]
  );

  useEffect(() => {
    /**
     * ForwardRef object initialization by the internal component's Ref object.
     * This is minor extending the reference functionality by existing internal properties.
     */
    if (ref) {
      if (typeof ref === "function") {
        ref(inputRef.current);
      } else {
        (ref as RefObject<HTMLInputElement | null>).current = inputRef.current
      }
    }
  }, [ref]);

  return (
    <div
      onClick={props.onClick}
      className={`relative flex items-center ${props.className}`}
    >
      <input
        ref={inputRef}
        name={props.name}
        value={props.value}
        form={props.form}
        type={"text"}
        onChange={onInputText}
        disabled={props.disabled}
        onFocus={focusHandler}
        required={required}
        onBlur={blurHandler}
        placeholder={props.placeholder}
        style={{
          width: props.style?.width || props.width || "100%",
          height: props.style?.height || props.height || (props.size ? sizes[props.size as TextInputSize] : sizes.default)
        }}
        className={`
          outline-none rounded-[4px] border border-dark-200 pl-[9px] 
          ${props.search ? "pr-[26px]" : "pr-[9px]"} text-[14px] 
          transition-colors focus:border-dark-800 placeholder:text-grey-500 placeholder:text-opacity-70
          ${props.inputClassName || ""}
        `}
      />
      <SearchIcon
        fill={focused ? "#FF8642" : "#1C1C1C"}
        width={12}
        height={12}
        className={`
          absolute right-[9px] opacity-0 -z-10 
          ${props.search && !focused && !props.icon && !props.iconSrc ? "opacity-100 !z-20" : ""}
        `}
      />
      <Image
        src={"/icons/close.svg"}
        alt={"close"}
        width={10}
        height={10}
        className={`
          absolute right-[9px] cursor-pointer opacity-0 -z-10 pointer-events-none 
          ${props.search && focused && !props.icon && !props.iconSrc ? "opacity-100 !z-20 pointer-events-auto" : ""}
        `}
        onMouseDown={clear}
      />
      {props.iconSrc && (
        <Image
          src={props.iconSrc}
          alt={"close"}
          width={props.iconSize?.width || 10}
          height={props.iconSize?.height || 10}
          className={`absolute right-[9px]`}
        />
      )}
      {props.icon && (
        <div className={"absolute right-[9px] flex items-center justify-center w-2.5 h-2.5"}>
          {props.icon}
        </div>
      )}
    </div>
  );
});