import clsx from "clsx";
import * as React from "react";
// import TextareaAutosize from "react-textarea-autosize";
import { useGetKey, useGetSet } from "../../hooks";
import { useDebugEvents } from "../../utils";
import { composeEventHandlers } from "../../utils/composeEvents";
import { useComposedRefs } from "../../utils/mergeRefs";
import * as styles from "./styles.module.css";

const TextareaAutosize = React.lazy(() => import("react-textarea-autosize"));

interface InputProps extends React.ComponentPropsWithoutRef<"textarea"> {
  minRows?: number;
  maxRows?: number;
  "data-id": string;
  "data-label"?: string;
  ref: React.Ref<HTMLTextAreaElement>;
  submitOnEnter?: boolean;
}

export function Textarea({
  ref,
  minRows,
  maxRows,
  defaultValue,
  onFocus,
  onChange,
  onBlur,
  onKeyDown,
  submitOnEnter = false,
  ...rest
}: InputProps) {
  const inputRef = React.useRef<HTMLTextAreaElement>(null!);
  const key = useGetKey(rest);
  const initialValue = React.useMemo(
    () => ({ value: defaultValue, focused: false }),
    [defaultValue],
  );
  const [{ value }, setState] = useGetSet(key, initialValue);
  const {
    className,
    onChange: handleChange,
    ...props
  } = useDebugEvents<Omit<InputProps, "ref">>(
    Object.assign(rest, {
      onFocus: composeEventHandlers(() => {
        setState(
          { focused: true },
          process.env.PREVIEW ? `onFocus` : undefined,
        );
      }, onFocus),
      onChange: composeEventHandlers(
        (event: React.ChangeEvent<HTMLInputElement>) => {
          const value = event.target.value;
          setState({ value }, process.env.PREVIEW ? `onChange` : undefined);
        },
        onChange,
      ),
      onBlur: composeEventHandlers(() => {
        setState(
          { focused: false },
          process.env.PREVIEW ? `onBlur` : undefined,
        );
      }, onBlur),
    }),
  );

  React.useEffect(() => {
    const parentForm = inputRef.current?.form;
    const handler = () => {
      setState({ value: defaultValue });
    };
    parentForm?.addEventListener("reset", handler);
    return () => {
      parentForm?.removeEventListener("reset", handler);
    };
  }, []);
  const finalRef = useComposedRefs(inputRef, ref);

  const handleKeyDown = React.useCallback(
    (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
      if (submitOnEnter && e.key === "Enter" && !e.shiftKey) {
        e.preventDefault();
        const parentForm = inputRef.current?.form;
        if (parentForm) {
          parentForm.requestSubmit();
        }
      }
    },
    [submitOnEnter],
  );

  const allProps = {
    ["data-component"]: "Textarea$Brevity",
    ...props,
    minRows,
    maxRows,
    ["data-id"]: key,
    ref: finalRef,
    className: clsx("textarea", styles.textarea, className),
    value: value ?? "",
    onChange: handleChange,
    onKeyDown: composeEventHandlers(handleKeyDown, onKeyDown),
  };

  return (
    <React.Suspense fallback={<textarea {...allProps} />}>
      <TextareaAutosize {...(allProps as any)} />
    </React.Suspense>
  );
}
