import { useEffect, useRef } from 'react';
import { createPortal } from 'react-dom';

/**
 * Inline text editor (S2).
 *
 * Renders a transparent <textarea> overlay positioned exactly over a
 * canvas text element so the user can edit the text in place rather than
 * jumping to the side panel. Activated by double-clicking a text element.
 *
 * Coordinates
 * ───────────
 * The Konva Stage uses a CSS transform (`scale(s)`) to fit the design
 * canvas into whatever DOM area is available. The text node's
 * `getClientRect({ relativeTo: stage })` returns coordinates in the
 * Stage's INTERNAL space (the canonical 300×300 design coords). To
 * place the textarea over the text on screen, we multiply those by the
 * stage's CSS scale factor and offset by the stage container's
 * page-level position.
 *
 *   pageX = stageBox.left + rect.x × cssScale
 *   pageY = stageBox.top  + rect.y × cssScale
 *
 * Rotation is intentionally NOT supported inline — rotated text would
 * need a CSS transform on the textarea, plus pointer events get weird.
 * For rotated/arc text, the side panel remains the editing surface;
 * double-click still selects the text, just doesn't open the inline
 * editor.
 *
 * Lifecycle
 * ─────────
 * Mount → focus the textarea, select all so the user can immediately
 * type to replace.
 * Input → onChange streams every keystroke to onUpdate (the same
 * updateSelectedElement path the side-panel textarea uses, with
 * center-preservation already applied by the App-level wrapper).
 * Dismiss → onCommit + onClose, fired on blur OR Escape.
 *
 * Enter/Return creates a newline (textarea default). Cmd/Ctrl+Enter
 * dismisses, mirroring most chat-UI conventions for "done editing".
 */
export function InlineTextEditor({ element, rect, onUpdate, onCommit, onClose }) {
  const textareaRef = useRef(null);

  // Focus + select-all on mount, so the user can immediately type to
  // replace the existing text. Running once via empty deps; the
  // textarea is keyed by element.id at the call site so a different
  // element triggers a remount.
  useEffect(() => {
    const ta = textareaRef.current;
    if (!ta) return;
    ta.focus();
    ta.select();
  }, []);

  if (!element || !rect) return null;

  const handleChange = (e) => {
    onUpdate?.({ text: e.target.value });
  };

  const handleKeyDown = (e) => {
    // Escape dismisses without committing the in-flight value (the
    // updates already streamed via onUpdate, and history will commit
    // them at onClose anyway). Cmd/Ctrl+Enter is the explicit-commit
    // shortcut. Plain Enter inserts a newline as expected.
    if (e.key === 'Escape') {
      e.preventDefault();
      onClose?.();
      return;
    }
    if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {
      e.preventDefault();
      onCommit?.();
      onClose?.();
    }
    // Stop propagation so global shortcuts (Delete, Backspace, [, ])
    // don't fire while the user is editing.
    e.stopPropagation();
  };

  const handleBlur = () => {
    onCommit?.();
    onClose?.();
  };

  // Match the rendered text's typography so what the user types lines
  // up visually with what they'll see when they're done editing. The
  // textarea sits on top of the text node, so any mismatch reads as
  // "the editor is in a different font than my text" — confusing.
  const fontSize = (element.fontSize || 24) * (rect.scale || 1);
  const style = {
    position: 'fixed',
    left: `${rect.left}px`,
    top: `${rect.top}px`,
    width: `${rect.width}px`,
    height: `${rect.height}px`,
    fontSize: `${fontSize}px`,
    fontFamily: element.fontFamily || 'DM Sans',
    color: element.fill || '#0f172a',
    background: 'rgba(255, 255, 255, 0.92)',
    border: '2px solid #ec4899',
    borderRadius: '4px',
    outline: 'none',
    padding: '2px 4px',
    margin: 0,
    resize: 'none',
    overflow: 'hidden',
    lineHeight: 1.2,
    textAlign: 'center',
    boxSizing: 'border-box',
    boxShadow: '0 0 0 4px rgba(236, 72, 153, 0.18)',
    zIndex: 1000,
  };

  return createPortal(
    <textarea
      ref={textareaRef}
      value={element.text ?? ''}
      onChange={handleChange}
      onKeyDown={handleKeyDown}
      onBlur={handleBlur}
      style={style}
      aria-label="Edit text inline"
    />,
    document.body,
  );
}
