// Rôle : centralise l'édition inline contrôlée pour inputs, textarea et titres contentEditable.
// Gère draft local, synchronisation, focus auto, commit blur/Enter et annulation Escape.
// À privilégier pour les libellés éditables avant de recréer une logique locale.
import { useEffect, useLayoutEffect, useRef, useState } from "react";

function getEditableText(element) {
  return element?.isContentEditable ? element.textContent : undefined;
}

export function useInlineEdit({
  value,
  onCommit,
  onCancel,
  onDone,
  transform = (draft) => String(draft || "").trim(),
  commitUnchanged = false,
  commitOnEnter = true,
  autoFocus = false,
  focusKey = "",
  blurOnEscape = false
}) {
  const inputRef = useRef(null);
  const skipCommitRef = useRef(false);
  const [draft, setDraft] = useState(value);

  function syncContentEditable(nextValue, force = false) {
    if (inputRef.current?.isContentEditable && (force || document.activeElement !== inputRef.current)) {
      inputRef.current.textContent = String(nextValue || "");
    }
  }

  useEffect(() => {
    setDraft(value);
    syncContentEditable(value);
  }, [value]);

  useLayoutEffect(() => {
    if (!autoFocus) return;
    inputRef.current?.focus();
  }, [autoFocus, focusKey]);

  function commit(rawDraft = draft) {
    if (skipCommitRef.current) {
      skipCommitRef.current = false;
      return;
    }
    const nextValue = transform(rawDraft);
    setDraft(nextValue);
    if (commitUnchanged || nextValue !== value) onCommit?.(nextValue);
    onDone?.();
  }

  function cancel(event) {
    setDraft(value);
    syncContentEditable(value, true);
    onCancel?.();
    onDone?.();
    if (blurOnEscape) {
      skipCommitRef.current = true;
      event?.currentTarget?.blur();
    }
  }

  function getEditHandlers(props) {
    return {
      onFocus: (event) => props.onFocus?.(event),
      onBlur: (event) => {
        commit(getEditableText(event.currentTarget) ?? draft);
        props.onBlur?.(event);
      },
      onKeyDown: (event) => {
        const contentEditable = event.currentTarget.isContentEditable;
        if (event.key === "Enter" && commitOnEnter) {
          if (contentEditable) event.preventDefault();
          event.currentTarget.blur();
        }
        if (event.key === "Escape") {
          if (contentEditable) event.preventDefault();
          cancel(event);
        }
        props.onKeyDown?.(event);
      }
    };
  }

  function getInputProps(props = {}) {
    return {
      ...props,
      ...getEditHandlers(props),
      ref: inputRef,
      value: draft,
      onChange: (event) => {
        setDraft(event.target.value);
        props.onChange?.(event);
      }
    };
  }

  function getContentEditableProps(props = {}) {
    return {
      ...props,
      ref: inputRef,
      ...getEditHandlers(props),
      contentEditable: true,
      suppressContentEditableWarning: true,
      spellCheck: props.spellCheck ?? "false"
    };
  }

  return {
    inputRef,
    draft,
    setDraft,
    commit,
    cancel,
    getInputProps,
    getContentEditableProps
  };
}
