// Rôle : fournit l'outil tableau avec cellules libres, formules simples et échange TSV.
import { useEffect, useMemo, useRef, useState } from "react";
import { Icon } from "../../../components/Icon.jsx";
import { useInlineEdit } from "../../../hooks/useInlineEdit.js";
import { TextExchangeActions } from "./TextExchangeActions.jsx";
import { cellAddress, columnIndexToName, evaluateTable, parseCellAddress } from "./tableFormulaEngine.js";

const DEFAULT_ROWS = 10;
const DEFAULT_COLUMNS = 6;
const MAX_ROWS = 50;
const MAX_COLUMNS = 20;
const MIN_COLUMN_WIDTH = 96;
const MAX_COLUMN_WIDTH = 220;
const MIN_ROW_HEADER_WIDTH = 42;
const MAX_ROW_HEADER_WIDTH = 180;

function cleanCells(cells, rows, columns) {
  const nextCells = {};
  for (let rowIndex = 0; rowIndex < rows; rowIndex += 1) {
    for (let columnIndex = 0; columnIndex < columns; columnIndex += 1) {
      const address = cellAddress(rowIndex, columnIndex);
      const value = String(cells?.[address] || "");
      if (value.trim()) nextCells[address] = value;
    }
  }
  return nextCells;
}

function cleanLabels(labels, length, getFallback) {
  const nextLabels = {};
  for (let index = 0; index < length; index += 1) {
    const value = String(labels?.[index] || "").slice(0, 80);
    if (value.trim() && value !== String(getFallback(index))) nextLabels[index] = value;
  }
  return nextLabels;
}

function estimateTextWidth(value, minWidth, maxWidth) {
  const length = String(value || "").length;
  return Math.min(maxWidth, Math.max(minWidth, 24 + length * 8));
}

function getColumnWidths(data, evaluatedCells) {
  return Array.from({ length: data.columns }, (_, columnIndex) => {
    let width = estimateTextWidth(data.columnLabels?.[columnIndex] || columnIndexToName(columnIndex), MIN_COLUMN_WIDTH, MAX_COLUMN_WIDTH);
    for (let rowIndex = 0; rowIndex < data.rows; rowIndex += 1) {
      const address = cellAddress(rowIndex, columnIndex);
      const value = evaluatedCells[address]?.display || data.cells[address] || "";
      width = Math.max(width, estimateTextWidth(value, MIN_COLUMN_WIDTH, MAX_COLUMN_WIDTH));
    }
    return width;
  });
}

function getRowHeaderWidth(data) {
  return Array.from({ length: data.rows }, (_, rowIndex) => data.rowLabels?.[rowIndex] || rowIndex + 1)
    .reduce((width, label) => Math.max(width, estimateTextWidth(label, MIN_ROW_HEADER_WIDTH, MAX_ROW_HEADER_WIDTH)), MIN_ROW_HEADER_WIDTH);
}

function getSelectionBounds(selection) {
  if (!selection?.anchor || !selection?.focus) return null;
  return {
    startRow: Math.min(selection.anchor.rowIndex, selection.focus.rowIndex),
    endRow: Math.max(selection.anchor.rowIndex, selection.focus.rowIndex),
    startColumn: Math.min(selection.anchor.columnIndex, selection.focus.columnIndex),
    endColumn: Math.max(selection.anchor.columnIndex, selection.focus.columnIndex)
  };
}

function isCellSelected(selection, rowIndex, columnIndex) {
  const bounds = getSelectionBounds(selection);
  return Boolean(bounds && rowIndex >= bounds.startRow && rowIndex <= bounds.endRow && columnIndex >= bounds.startColumn && columnIndex <= bounds.endColumn);
}

function isMultiCellSelection(selection) {
  const bounds = getSelectionBounds(selection);
  return Boolean(bounds && (bounds.startRow !== bounds.endRow || bounds.startColumn !== bounds.endColumn));
}

function clampCellPosition(rowIndex, columnIndex, rows, columns) {
  return {
    rowIndex: Math.min(rows - 1, Math.max(0, rowIndex)),
    columnIndex: Math.min(columns - 1, Math.max(0, columnIndex))
  };
}

function getRangeAddresses(selection) {
  const bounds = getSelectionBounds(selection);
  if (!bounds) return [];
  const addresses = [];
  for (let rowIndex = bounds.startRow; rowIndex <= bounds.endRow; rowIndex += 1) {
    for (let columnIndex = bounds.startColumn; columnIndex <= bounds.endColumn; columnIndex += 1) {
      addresses.push(cellAddress(rowIndex, columnIndex));
    }
  }
  return addresses;
}

function getFormulaRangeText(selection) {
  const addresses = getRangeAddresses(selection);
  if (!addresses.length) return "";
  return addresses.length === 1 ? addresses[0] : `(${addresses.join("+")})`;
}

export function TableModule({ toolboxId, moduleId, context, editing }) {
  const data = context.normalizeTableData(context.getModuleData(toolboxId, moduleId, { rows: DEFAULT_ROWS, columns: DEFAULT_COLUMNS, cells: {} }));
  const textContent = context.moduleText?.table || {};
  const [editingCell, setEditingCell] = useState("");
  const [highlightedCell, setHighlightedCell] = useState("");
  const [selection, setSelection] = useState(null);
  const draggingSelectionRef = useRef(false);
  const formulaSelectionRef = useRef(null);
  const inputRefs = useRef(new Map());
  const highlightTimeoutRef = useRef(0);
  const evaluatedCells = useMemo(() => evaluateTable(data.cells, data), [data]);
  const columnWidths = useMemo(() => getColumnWidths(data, evaluatedCells), [data, evaluatedCells]);
  const rowHeaderWidth = useMemo(() => getRowHeaderWidth(data), [data]);

  useEffect(() => {
    function stopSelectionDrag() {
      if (formulaSelectionRef.current) {
        const formulaSelection = formulaSelectionRef.current;
        formulaSelectionRef.current = null;
        draggingSelectionRef.current = false;
        insertFormulaReferenceSelection(formulaSelection);
        return;
      }
      draggingSelectionRef.current = false;
    }

    window.addEventListener("pointerup", stopSelectionDrag);
    return () => window.removeEventListener("pointerup", stopSelectionDrag);
  });

  function save(nextData) {
    context.setModuleData(toolboxId, moduleId, nextData, "table");
  }

  function setCellValue(address, value) {
    const nextCells = { ...data.cells };
    if (String(value || "").trim()) {
      nextCells[address] = value;
    } else {
      delete nextCells[address];
    }
    save({ ...data, cells: nextCells });
  }

  function clearSelection(rowIndex, columnIndex) {
    const nextCells = { ...data.cells };
    const bounds = getSelectionBounds(selection) || {
      startRow: rowIndex,
      endRow: rowIndex,
      startColumn: columnIndex,
      endColumn: columnIndex
    };

    for (let selectedRowIndex = bounds.startRow; selectedRowIndex <= bounds.endRow; selectedRowIndex += 1) {
      for (let selectedColumnIndex = bounds.startColumn; selectedColumnIndex <= bounds.endColumn; selectedColumnIndex += 1) {
        delete nextCells[cellAddress(selectedRowIndex, selectedColumnIndex)];
      }
    }

    save({ ...data, cells: nextCells });
    const focusedAddress = cellAddress(rowIndex, columnIndex);
    window.requestAnimationFrame(() => inputRefs.current.get(focusedAddress)?.focus());
  }

  function resize(rows, columns) {
    save({
      rows,
      columns,
      cells: cleanCells(data.cells, rows, columns),
      rowLabels: cleanLabels(data.rowLabels, rows, (rowIndex) => rowIndex + 1),
      columnLabels: cleanLabels(data.columnLabels, columns, columnIndexToName)
    });
  }

  function setColumnLabel(columnIndex, value) {
    const nextLabels = { ...data.columnLabels };
    const nextValue = String(value || "").slice(0, 80);
    if (nextValue.trim() && nextValue !== columnIndexToName(columnIndex)) {
      nextLabels[columnIndex] = nextValue;
    } else {
      delete nextLabels[columnIndex];
    }
    save({ ...data, columnLabels: nextLabels });
  }

  function setRowLabel(rowIndex, value) {
    const nextLabels = { ...data.rowLabels };
    const nextValue = String(value || "").slice(0, 80);
    if (nextValue.trim() && nextValue !== String(rowIndex + 1)) {
      nextLabels[rowIndex] = nextValue;
    } else {
      delete nextLabels[rowIndex];
    }
    save({ ...data, rowLabels: nextLabels });
  }

  function registerInput(address, element) {
    if (element) {
      inputRefs.current.set(address, element);
    } else {
      inputRefs.current.delete(address);
    }
  }

  function getActiveFormulaInput() {
    if (!editingCell) return null;
    const input = inputRefs.current.get(editingCell);
    const value = data.cells[editingCell] || "";
    return input && value.startsWith("=") ? input : null;
  }

  function focusCell(rowIndex, columnIndex, options = {}) {
    const position = clampCellPosition(rowIndex, columnIndex, data.rows, data.columns);
    const address = cellAddress(position.rowIndex, position.columnIndex);
    window.requestAnimationFrame(() => {
      const input = inputRefs.current.get(address);
      input?.focus();
      if (options.select) {
        input?.select();
      } else {
        input?.setSelectionRange(input.value.length, input.value.length);
      }
    });
  }

  function startEditing(address, initialValue = null, options = {}) {
    const nextValue = initialValue == null ? data.cells[address] || "" : initialValue;
    if (initialValue != null) setCellValue(address, initialValue);
    setEditingCell(address);
    window.requestAnimationFrame(() => {
      const input = inputRefs.current.get(address);
      input?.focus();
      if (options.select) {
        input?.select();
      } else {
        const position = options.caret ?? nextValue.length;
        input?.setSelectionRange(position, position);
      }
    });
  }

  function stopEditing(address) {
    setEditingCell("");
    const parsed = parseCellAddress(address);
    if (parsed) focusCell(parsed.rowIndex, parsed.columnIndex);
  }

  function insertFormulaText(text, options = {}) {
    const input = getActiveFormulaInput();
    if (!input || !text) return false;

    const currentValue = data.cells[editingCell] || "";
    const start = options.start ?? input.selectionStart ?? currentValue.length;
    const end = options.end ?? input.selectionEnd ?? start;
    const nextValue = `${currentValue.slice(0, start)}${text}${currentValue.slice(end)}`;
    setCellValue(editingCell, nextValue);
    setHighlightedCell(options.highlightedCell || text);
    window.clearTimeout(highlightTimeoutRef.current);
    highlightTimeoutRef.current = window.setTimeout(() => setHighlightedCell(""), 700);
    window.requestAnimationFrame(() => {
      input.focus();
      input.setSelectionRange(start + text.length, start + text.length);
    });
    return true;
  }

  function insertFormulaReferenceSelection(formulaSelection) {
    const text = getFormulaRangeText({ anchor: formulaSelection.anchor, focus: formulaSelection.focus });
    insertFormulaText(text, {
      start: formulaSelection.start,
      end: formulaSelection.end,
      highlightedCell: cellAddress(formulaSelection.focus.rowIndex, formulaSelection.focus.columnIndex)
    });
  }

  function getTsv(bounds = null) {
    const rows = [];
    const startRow = bounds?.startRow ?? 0;
    const endRow = bounds?.endRow ?? data.rows - 1;
    const startColumn = bounds?.startColumn ?? 0;
    const endColumn = bounds?.endColumn ?? data.columns - 1;

    for (let rowIndex = startRow; rowIndex <= endRow; rowIndex += 1) {
      const columns = [];
      for (let columnIndex = startColumn; columnIndex <= endColumn; columnIndex += 1) {
        columns.push(evaluatedCells[cellAddress(rowIndex, columnIndex)]?.display || "");
      }
      rows.push(columns.join("\t"));
    }
    return rows.join("\n");
  }

  async function copyTsv() {
    const text = getTsv(isMultiCellSelection(selection) ? getSelectionBounds(selection) : null);
    if (!await context.copyText(text)) return;
    context.notify?.(textContent.copiedTitle || "Tableau copié");
  }

  async function copySelection(event) {
    if (!selection || !(event.ctrlKey || event.metaKey) || event.key.toLowerCase() !== "c") return;
    event.preventDefault();
    const text = getTsv(getSelectionBounds(selection));
    if (!await context.copyText(text)) return;
    context.notify?.(textContent.copiedTitle || "Tableau copié");
  }

  function selectCell(rowIndex, columnIndex, extend = false) {
    const cell = { rowIndex, columnIndex };
    setSelection((currentSelection) => extend && currentSelection?.anchor
      ? { anchor: currentSelection.anchor, focus: cell }
      : { anchor: cell, focus: cell });
  }

  function extendSelection(rowIndex, columnIndex) {
    const cell = { rowIndex, columnIndex };
    setSelection((currentSelection) => currentSelection?.anchor
      ? { anchor: currentSelection.anchor, focus: cell }
      : { anchor: cell, focus: cell });
  }

  function startFormulaSelection(rowIndex, columnIndex) {
    const input = getActiveFormulaInput();
    const formulaCell = parseCellAddress(editingCell);
    if (!input || (formulaCell?.rowIndex === rowIndex && formulaCell?.columnIndex === columnIndex)) return false;
    const cell = { rowIndex, columnIndex };
    formulaSelectionRef.current = {
      anchor: cell,
      focus: cell,
      start: input.selectionStart ?? (data.cells[editingCell] || "").length,
      end: input.selectionEnd ?? input.selectionStart ?? (data.cells[editingCell] || "").length
    };
    setSelection({ anchor: cell, focus: cell });
    draggingSelectionRef.current = true;
    return true;
  }

  function extendFormulaSelection(rowIndex, columnIndex) {
    if (!formulaSelectionRef.current) return false;
    const focus = { rowIndex, columnIndex };
    formulaSelectionRef.current = { ...formulaSelectionRef.current, focus };
    setSelection({ anchor: formulaSelectionRef.current.anchor, focus });
    return true;
  }

  function handleCellKeyDown(event, rowIndex, columnIndex, address, isEditing) {
    if (!isEditing && (event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "c") {
      copySelection(event);
      return;
    }

    if (!isEditing && event.key === "Delete") {
      event.preventDefault();
      clearSelection(rowIndex, columnIndex);
      return;
    }

    if (event.key === "Escape") {
      event.preventDefault();
      formulaSelectionRef.current = null;
      draggingSelectionRef.current = false;
      setEditingCell("");
      setSelection({ anchor: { rowIndex, columnIndex }, focus: { rowIndex, columnIndex } });
      focusCell(rowIndex, columnIndex);
      return;
    }

    if (!isEditing && event.key === "Enter") {
      event.preventDefault();
      startEditing(address, null, { select: true });
      return;
    }

    const deltas = {
      ArrowUp: [-1, 0],
      ArrowDown: [1, 0],
      ArrowLeft: [0, -1],
      ArrowRight: [0, 1],
      Enter: [event.shiftKey ? -1 : 1, 0],
      Tab: [0, event.shiftKey ? -1 : 1]
    };
    const delta = deltas[event.key];
    if (!delta) {
      if (!isEditing && event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
        event.preventDefault();
        startEditing(address, event.key, { caret: event.key.length });
      }
      return;
    }

    const input = event.currentTarget;
    const valueLength = input.value.length;
    const caretStart = input.selectionStart ?? valueLength;
    const caretEnd = input.selectionEnd ?? caretStart;
    const hasTextSelection = caretStart !== caretEnd;
    const isHorizontalArrow = event.key === "ArrowLeft" || event.key === "ArrowRight";
    const canMoveHorizontal = event.key === "ArrowLeft" ? caretStart === 0 : caretEnd === valueLength;
    const shouldNavigate = !isEditing || event.key === "Tab" || event.key === "Enter" || event.shiftKey || !isHorizontalArrow || (!hasTextSelection && canMoveHorizontal);

    if (!shouldNavigate) return;

    event.preventDefault();
    setEditingCell("");
    const nextCell = clampCellPosition(rowIndex + delta[0], columnIndex + delta[1], data.rows, data.columns);
    if (event.shiftKey && event.key.startsWith("Arrow")) {
      extendSelection(nextCell.rowIndex, nextCell.columnIndex);
    } else {
      selectCell(nextCell.rowIndex, nextCell.columnIndex);
    }
    focusCell(nextCell.rowIndex, nextCell.columnIndex);
  }

  return (
    <div className="table-module">
      {editing && (
        <div className="module-add-panel table-exchange-panel">
          <TextExchangeActions type="table" data={data} context={context} textContent={textContent} exportLabel="Exporter TSV" onImport={(nextData) => context.setModuleData(toolboxId, moduleId, nextData, "table")} />
        </div>
      )}
      <div className="notepad-toolbar table-toolbar" aria-label={textContent.toolbarLabel || "Actions du tableau"}>
        <div className="notepad-format-controls table-controls">
          <div className="notepad-toolbar-group" role="group" aria-label={textContent.rowActionsLabel || "Lignes"}>
            <button
              className="notepad-toolbar-button"
              type="button"
              onClick={() => resize(Math.min(MAX_ROWS, data.rows + 1), data.columns)}
              disabled={data.rows >= MAX_ROWS}
              aria-label={textContent.addRowTitle || "Ajouter une ligne"}
              title={textContent.addRowTitle || "Ajouter une ligne"}
            >
              <Icon name="add-row" />
            </button>
            <button
              className="notepad-toolbar-button danger"
              type="button"
              onClick={() => resize(Math.max(1, data.rows - 1), data.columns)}
              disabled={data.rows <= 1}
              aria-label={textContent.removeRowTitle || "Supprimer la dernière ligne"}
              title={textContent.removeRowTitle || "Supprimer la dernière ligne"}
            >
              <Icon name="remove-row" />
            </button>
          </div>
          <div className="notepad-toolbar-group" role="group" aria-label={textContent.columnActionsLabel || "Colonnes"}>
            <button
              className="notepad-toolbar-button"
              type="button"
              onClick={() => resize(data.rows, Math.min(MAX_COLUMNS, data.columns + 1))}
              disabled={data.columns >= MAX_COLUMNS}
              aria-label={textContent.addColumnTitle || "Ajouter une colonne"}
              title={textContent.addColumnTitle || "Ajouter une colonne"}
            >
              <Icon name="add-column" />
            </button>
            <button
              className="notepad-toolbar-button danger"
              type="button"
              onClick={() => resize(data.rows, Math.max(1, data.columns - 1))}
              disabled={data.columns <= 1}
              aria-label={textContent.removeColumnTitle || "Supprimer la dernière colonne"}
              title={textContent.removeColumnTitle || "Supprimer la dernière colonne"}
            >
              <Icon name="remove-column" />
            </button>
          </div>
          <div className="notepad-toolbar-group table-size-group" aria-label={textContent.sizeLabel || "Taille du tableau"}>
            <span className="table-size-indicator">{data.rows} x {data.columns}</span>
          </div>
        </div>
        <div className="notepad-toolbar-group table-copy-group">
          <button
            className="notepad-toolbar-button table-copy-button"
            type="button"
            onClick={copyTsv}
            aria-label={textContent.copyTitle || "Copier les valeurs"}
            title={textContent.copyTitle || "Copier les valeurs"}
          >
            <Icon name="copy" />
            <span>{textContent.copyTitle || "Copier les valeurs"}</span>
          </button>
        </div>
      </div>
      <div className="table-grid-wrap legacy-scrollbar">
        <div
          className="table-grid"
          style={{
            "--table-columns": `${rowHeaderWidth}px ${columnWidths.map((width) => `minmax(${width}px, 1fr)`).join(" ")}`,
            "--table-min-width": `${rowHeaderWidth + columnWidths.reduce((total, width) => total + width, 0)}px`
          }}
          role="grid"
          aria-label={textContent.gridLabel || "Tableau"}
        >
          <span className="table-corner" aria-hidden="true" />
          {Array.from({ length: data.columns }, (_, columnIndex) => (
            <HeaderLabelInput
              className="table-header-cell table-header-input"
              key={columnIndex}
              value={data.columnLabels?.[columnIndex] || columnIndexToName(columnIndex)}
              fallback={columnIndexToName(columnIndex)}
              onSave={(value) => setColumnLabel(columnIndex, value)}
              aria-label={`${textContent.columnLabel || "Intitulé de colonne"} ${columnIndexToName(columnIndex)}`}
              title={`${columnIndexToName(columnIndex)} - ${textContent.columnFormulaTitle || "Référence conservée dans les formules"}`}
            />
          ))}
          {Array.from({ length: data.rows }, (_, rowIndex) => (
            <TableRow
              key={rowIndex}
              rowIndex={rowIndex}
              columns={data.columns}
              cells={data.cells}
              evaluatedCells={evaluatedCells}
              editingCell={editingCell}
              highlightedCell={highlightedCell}
              textContent={textContent}
              rowLabel={data.rowLabels?.[rowIndex] || ""}
              selection={selection}
              onRowLabelChange={setRowLabel}
              onFocus={(cell) => {
                const parsed = parseCellAddress(cell);
                if (parsed && !selection) selectCell(parsed.rowIndex, parsed.columnIndex);
              }}
              onBlur={(cell) => {
                if (editingCell === cell) setEditingCell("");
              }}
              onCellChange={setCellValue}
              onFormulaSelectionStart={startFormulaSelection}
              onFormulaSelectionExtend={extendFormulaSelection}
              onSelectCell={selectCell}
              onExtendSelection={extendSelection}
              draggingSelectionRef={draggingSelectionRef}
              onCellKeyDown={handleCellKeyDown}
              onStartEditing={startEditing}
              registerInput={registerInput}
            />
          ))}
        </div>
      </div>
    </div>
  );
}

function TableRow({ rowIndex, columns, cells, evaluatedCells, editingCell, highlightedCell, textContent, rowLabel, selection, onRowLabelChange, onFocus, onBlur, onCellChange, onFormulaSelectionStart, onFormulaSelectionExtend, onSelectCell, onExtendSelection, draggingSelectionRef, onCellKeyDown, onStartEditing, registerInput }) {
  return (
    <>
      <HeaderLabelInput
        className="table-row-header table-header-input"
        value={rowLabel || String(rowIndex + 1)}
        fallback={String(rowIndex + 1)}
        onSave={(value) => onRowLabelChange(rowIndex, value)}
        aria-label={`${textContent.rowLabel || "Intitulé de ligne"} ${rowIndex + 1}`}
        title={`${rowIndex + 1} - ${textContent.rowFormulaTitle || "Référence conservée dans les formules"}`}
      />
      {Array.from({ length: columns }, (_, columnIndex) => {
        const address = cellAddress(rowIndex, columnIndex);
        const rawValue = cells[address] || "";
        const evaluated = evaluatedCells[address];
        const isEditing = editingCell === address;
        const isFormula = rawValue.startsWith("=");
        const displayValue = isEditing ? rawValue : evaluated?.display || rawValue;
        const className = [
          "table-cell-input",
          isEditing ? "is-editing" : "",
          isFormula ? "is-formula" : "",
          evaluated?.error && evaluated.error !== "empty" && !isEditing ? "has-error" : "",
          isCellSelected(selection, rowIndex, columnIndex) ? "is-selected" : "",
          highlightedCell === address ? "is-referenced" : ""
        ].filter(Boolean).join(" ");

        return (
          <input
            key={address}
            ref={(element) => registerInput(address, element)}
            className={className}
            value={displayValue}
            onMouseDown={(event) => {
              if (onFormulaSelectionStart(rowIndex, columnIndex)) {
                event.preventDefault();
              } else {
                draggingSelectionRef.current = true;
                onSelectCell(rowIndex, columnIndex, event.shiftKey);
              }
            }}
            onDoubleClick={() => onStartEditing(address, null, { select: true })}
            onMouseEnter={() => {
              if (onFormulaSelectionExtend(rowIndex, columnIndex)) return;
              if (draggingSelectionRef.current) onExtendSelection(rowIndex, columnIndex);
            }}
            onFocus={() => onFocus(address)}
            onBlur={() => onBlur(address)}
            onChange={(event) => onCellChange(address, event.target.value)}
            onKeyDown={(event) => onCellKeyDown(event, rowIndex, columnIndex, address, isEditing)}
            aria-label={`${textContent.cellLabel || "Cellule"} ${address}`}
            title={evaluated?.error && evaluated.error !== "empty" ? textContent.errorTitle || "Formule invalide" : address}
            inputMode="text"
            readOnly={!isEditing}
            spellCheck="false"
          />
        );
      })}
    </>
  );
}

function HeaderLabelInput({ className, value, fallback, onSave, ...props }) {
  const inlineEdit = useInlineEdit({
    value,
    onCommit: onSave,
    transform: (draft) => String(draft || ""),
    blurOnEscape: true
  });

  return (
    <input
      {...inlineEdit.getInputProps({
        ...props,
        className,
        onFocus: (event) => {
          if (value === fallback) window.requestAnimationFrame(() => event.target.select());
        },
        spellCheck: "false"
      })}
    />
  );
}
