import { forwardRef } from "react";
import TextareaAutoSize, {
  type TextareaAutosizeProps,
} from "react-textarea-autosize";
import { useCallbackRef, useMergeRefs } from "use-callback-ref";

import type { InputProps } from "../input/Input";
import { twMerge } from "../../../tailwind.config";
import { InputLabel } from "../inputLabel/InputLabel";
import { fieldClasses, inputClasses } from "../input/Input.styles";
import { InputCounter } from "../input/InputCounter";
import { RequiredIndicator } from "../input/RequiredIndicator";
import { useTrackedValue } from "../input/useTrackedValue";
import { ClearButton } from "../input/ClearButton";
import { ErrorIcon } from "../input/ErrorIcon";

export type TextareaProps = Pick<
  InputProps,
  | "variant"
  | "height"
  | "label"
  | "fullWidth"
  | "error"
  | "errorText"
  | "onClear"
  | "clearButton"
  | "ESCAPE_className"
> &
  TextareaAutosizeProps;

export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
  (
    {
      variant = "outlined",
      height = "40",
      label,
      id,
      fullWidth = false,
      disabled = false,
      required = false,
      error = false,
      errorText,
      maxLength,
      onChange,
      clearButton = true,
      onClear,
      ESCAPE_className,
      ...restProps
    },
    ref
  ) => {
    const [value, takeValueSnapshot, handleChange] = useTrackedValue(onChange);
    const localRef = useCallbackRef<HTMLTextAreaElement>(
      null,
      takeValueSnapshot
    );
    const mergedRef = useMergeRefs([localRef, ref]);

    return (
      <div
        className={twMerge(
          fullWidth ? "flex" : "inline-flex",
          "flex-col",
          ESCAPE_className
        )}
      >
        {typeof label === "string" ? (
          <InputLabel htmlFor={id}>{label}</InputLabel>
        ) : (
          label
        )}
        <div
          className={inputClasses({
            variant,
            height,
            disabled,
            error,
          })}
        >
          <TextareaAutoSize
            ref={mergedRef}
            id={id}
            onChange={handleChange}
            disabled={disabled}
            className={twMerge(
              fieldClasses({ variant }),
              "resize-none overflow-auto"
            )}
            maxLength={maxLength}
            {...restProps}
          />
          {clearButton && !disabled && (
            <ClearButton
              hidden={value === ""}
              inputRef={localRef}
              onChange={handleChange}
              onClear={onClear}
            />
          )}
          {error && <ErrorIcon errorText={errorText} />}
          {required && <RequiredIndicator />}
          {maxLength !== undefined ? (
            <InputCounter maxLength={maxLength} value={value} />
          ) : null}
        </div>
      </div>
    );
  }
);

Textarea.displayName = "Textarea";
