import { useEffect, useLayoutEffect, useRef, useState } from "react";
import { createComposerDraftCommitter } from "./composer-draft.js";
import { shouldSubmitComposerKey, usesCompactComposerKeyboard } from "./composer-keyboard.js";
import { resizeComposerInput } from "./composer-resize.js";

export function ComposerTextInput({
  sessionId,
  value,
  inputRef,
  placeholder,
  disabled,
  onDraftChange,
  onValueChange,
  onPresenceChange,
  onFocus,
  onBlur,
  onSubmit
}) {
  const [draft, setDraft] = useState(() => value);
  const draftRef = useRef(value);
  const presenceRef = useRef(Boolean(value.trim()));
  const sessionIdRef = useRef(sessionId);
  const onDraftChangeRef = useRef(onDraftChange);
  onDraftChangeRef.current = onDraftChange;
  const committerRef = useRef(null);
  if (!committerRef.current) {
    committerRef.current = createComposerDraftCommitter((nextValue, targetSessionId) => {
      onDraftChangeRef.current(nextValue, targetSessionId);
    });
    committerRef.current.replace(value, sessionId);
  }

  function updatePresence(nextValue) {
    const present = Boolean(nextValue.trim());
    if (present === presenceRef.current) return;
    presenceRef.current = present;
    onPresenceChange(present);
  }

  function updateDraft(nextValue) {
    draftRef.current = nextValue;
    setDraft(nextValue);
    onValueChange(nextValue);
    updatePresence(nextValue);
    committerRef.current.schedule(nextValue, sessionId);
  }

  useEffect(() => {
    if (sessionIdRef.current !== sessionId) committerRef.current.flush();
    sessionIdRef.current = sessionId;
    draftRef.current = value;
    setDraft(value);
    onValueChange(value);
    updatePresence(value);
    committerRef.current.replace(value, sessionId);
  }, [sessionId, value]);

  useEffect(() => {
    const flushDraft = () => committerRef.current.flush();
    const flushHiddenDraft = () => {
      if (globalThis.document?.visibilityState === "hidden") flushDraft();
    };
    globalThis.addEventListener?.("pagehide", flushDraft);
    globalThis.document?.addEventListener?.("visibilitychange", flushHiddenDraft);
    return () => {
      flushDraft();
      globalThis.removeEventListener?.("pagehide", flushDraft);
      globalThis.document?.removeEventListener?.("visibilitychange", flushHiddenDraft);
    };
  }, []);

  useLayoutEffect(() => {
    resizeComposerInput(inputRef.current);
  }, [draft, inputRef]);

  return <textarea className="composer-input" ref={inputRef} rows="1" value={draft} onFocus={onFocus} onBlur={() => { committerRef.current.flush(); onBlur(); }} onChange={(event) => updateDraft(event.target.value)} placeholder={placeholder} disabled={disabled} onKeyDown={(event) => { if (shouldSubmitComposerKey(event, { compact: usesCompactComposerKeyboard() })) { event.preventDefault(); void onSubmit(draftRef.current); } }} />;
}
