(function initFivaHardPasteEngine(global) {
  "use strict";

  if (global.FIVA?.HardPasteEngine) return;

  function wait(ms = 50, signal) {
    if (signal?.aborted) return Promise.resolve(false);
    return new Promise((resolve) => {
      const timer = setTimeout(() => {
        signal?.removeEventListener?.("abort", onAbort);
        resolve(true);
      }, ms);
      function onAbort() {
        clearTimeout(timer);
        resolve(false);
      }
      signal?.addEventListener?.("abort", onAbort, { once: true });
    });
  }

  function humanDelay(signal) {
    return wait(30 + Math.floor(Math.random() * 51), signal);
  }

  function fire(control, type, init = {}) {
    control.dispatchEvent(new Event(type, { bubbles: true, cancelable: true, ...init }));
  }

  function key(control, type, keyName, options = {}) {
    control.dispatchEvent(new KeyboardEvent(type, {
      bubbles: true,
      cancelable: true,
      key: keyName,
      code: options.code || keyName,
      ctrlKey: options.ctrlKey === true,
      metaKey: options.metaKey === true
    }));
  }

  function input(control, value) {
    try {
      control.dispatchEvent(new InputEvent("beforeinput", {
        bubbles: true,
        cancelable: true,
        data: value,
        inputType: "insertFromPaste"
      }));
    } catch (_) {
      fire(control, "beforeinput");
    }
    fire(control, "input");
  }

  function trace(options = {}, message, level = "info") {
    if (typeof options.onTrace === "function") options.onTrace(message, level);
  }

  function nativeSetter(control, value) {
    const proto = control.tagName === "TEXTAREA" ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype;
    const descriptor = Object.getOwnPropertyDescriptor(proto, "value");
    if (descriptor?.set) descriptor.set.call(control, value);
    else control.value = value;
  }

  function activate(control) {
    control.scrollIntoView({ block: "center", inline: "nearest" });
    control.dispatchEvent(new MouseEvent("mouseover", { bubbles: true, cancelable: true }));
    control.dispatchEvent(new MouseEvent("mousedown", { bubbles: true, cancelable: true }));
    control.focus({ preventScroll: true });
    control.click();
    control.dispatchEvent(new MouseEvent("mouseup", { bubbles: true, cancelable: true }));
  }

  function normalize(value = "") {
    return String(value || "").replace(/\s+/g, " ").trim();
  }

  function defaultVerify(control, expected) {
    return normalize(control.value) === normalize(expected);
  }

  async function clearForTyping(control, signal) {
    key(control, "keydown", "a", { ctrlKey: true, code: "KeyA" });
    key(control, "keypress", "a", { ctrlKey: true, code: "KeyA" });
    key(control, "keyup", "a", { ctrlKey: true, code: "KeyA" });
    await humanDelay(signal);
    key(control, "keydown", "Backspace", { code: "Backspace" });
    nativeSetter(control, "");
    input(control, "");
    key(control, "keyup", "Backspace", { code: "Backspace" });
    fire(control, "change");
    try {
      if (typeof control.setSelectionRange === "function") control.setSelectionRange(0, 0);
    } catch (_) {
      // Specialized inputs may not expose text selection.
    }
    await humanDelay(signal);
  }

  async function simulateTyping(control, value, options = {}) {
    const expected = String(value || "");
    const signal = options.signal;
    const verify = typeof options.verify === "function" ? options.verify : defaultVerify;
    if (!control || !expected || signal?.aborted) return false;

    activate(control);
    await humanDelay(signal);
    await clearForTyping(control, signal);

    for (const char of expected) {
      if (signal?.aborted) return false;
      const start = Number.isFinite(control.selectionStart) ? control.selectionStart : String(control.value || "").length;
      const end = Number.isFinite(control.selectionEnd) ? control.selectionEnd : start;
      key(control, "keydown", char, { code: char.length === 1 ? `Key${char.toUpperCase()}` : char });
      key(control, "keypress", char, { code: char.length === 1 ? `Key${char.toUpperCase()}` : char });
      const before = String(control.value || "").slice(0, start);
      const after = String(control.value || "").slice(end);
      const nextValue = `${before}${char}${after}`;
      nativeSetter(control, nextValue);
      try {
        if (typeof control.setSelectionRange === "function") {
          const nextCaret = start + char.length;
          control.setSelectionRange(nextCaret, nextCaret);
        }
      } catch (_) {
        // Date and specialized inputs can reject text selections.
      }
      input(control, char);
      key(control, "keyup", char, { code: char.length === 1 ? `Key${char.toUpperCase()}` : char });
      await humanDelay(signal);
    }

    fire(control, "change");
    await humanDelay(signal);
    control.blur();
    fire(control, "blur");
    return verify(control, expected);
  }

  async function fillText(control, value, options = {}) {
    const expected = String(value || "");
    const signal = options.signal;
    const verify = typeof options.verify === "function" ? options.verify : defaultVerify;
    const attempts = Math.max(1, Math.min(Number(options.attempts || 2), 2));
    if (!control || !expected || signal?.aborted) return false;

    const wasReadOnly = control.readOnly === true;
    if (wasReadOnly) {
      control.readOnly = false;
      control.removeAttribute("readonly");
    }

    try {
      for (let attempt = 0; attempt < attempts; attempt += 1) {
        if (signal?.aborted) return false;
        activate(control);
        await humanDelay(signal);

        key(control, "keydown", "a", { ctrlKey: true, code: "KeyA" });
        key(control, "keypress", "a", { ctrlKey: true, code: "KeyA" });
        key(control, "keyup", "a", { ctrlKey: true, code: "KeyA" });
        await humanDelay(signal);

        key(control, "keydown", "Backspace", { code: "Backspace" });
        nativeSetter(control, "");
        input(control, "");
        key(control, "keyup", "Backspace", { code: "Backspace" });
        fire(control, "change");
        await humanDelay(signal);

        key(control, "keydown", "v", { ctrlKey: true, code: "KeyV" });
        key(control, "keypress", "v", { ctrlKey: true, code: "KeyV" });
        nativeSetter(control, expected);
        input(control, expected);
        key(control, "keyup", "v", { ctrlKey: true, code: "KeyV" });
        fire(control, "change");
        await humanDelay(signal);
        control.blur();
        fire(control, "blur");

        if (verify(control, expected)) {
          trace(options, "hard-paste success");
          return true;
        }
        trace(options, `hard-paste retry ${attempt + 1}`, "warn");
      }
      trace(options, "hard-paste typing fallback", "warn");
      const typed = await simulateTyping(control, expected, options);
      if (typed) trace(options, "typing fallback success");
      else trace(options, "hard-paste failed", "error");
      return typed;
    } finally {
      if (wasReadOnly) {
        control.readOnly = true;
        control.setAttribute("readonly", "readonly");
      }
    }
  }

  const HardPasteEngine = Object.freeze({
    fillText,
    humanDelay,
    nativeSetter,
    smartInputInsert: fillText,
    simulateTyping,
    wait
  });

  global.FIVA = Object.assign(global.FIVA || {}, { HardPasteEngine });
})(typeof globalThis !== "undefined" ? globalThis : this);
