(function () {
  const honeypotState = new WeakMap();
  const cfg = mergeConfig(window.WPSH_CONFIG, window.WPSH_AUTO_CONFIG);
  const autoProtectCfg = normalizeAutoProtectConfig(cfg.autoProtect);
  const hasFormContexts = Array.isArray(cfg.contexts) && cfg.contexts.length > 0;
  const dynamicDomSupport = !!cfg.dynamicDomSupport;
  if (!cfg || !cfg.restUrl || (!hasFormContexts && !autoProtectCfg.enabled)) {
    return;
  }
  const i18n = cfg.messages || {};
  const showDebugUi = false;
  const challengeEndpointCandidates = buildChallengeEndpoints(cfg.restUrl);

  if (hasFormContexts) {
    scanDocument();
    installFormPayloadHooks();
    if (dynamicDomSupport) {
      observeDynamicForms();
      installLazyFormHooks();
    }
  }
  if (autoProtectCfg.enabled) {
    installAutoEndpointProtection();
  }

  function attach(form, ctx) {
    if (!form || form.dataset.wpshAttached === "1") {
      return;
    }
    form.dataset.wpshAttached = "1";

    ensureHidden(form, "wpsh_pow");
    ensureHidden(form, "wpsh_ctr");
    ensureHidden(form, "wpsh_hash");
    ensureHidden(form, "wpsh_ctx").value = ctx;
    ensureHidden(form, "wpsh_required").value = ctx.startsWith("form:") ? "1" : "0";
    syncElementorMirrorFields(form, ctx);
    ensureHoneypot(form);

    const ui = createStatusUI(form, ctx);
    const submitBtn = form.querySelector('button[type="submit"], input[type="submit"]');
    if (submitBtn instanceof HTMLButtonElement || submitBtn instanceof HTMLInputElement) {
      submitBtn.disabled = false;
      submitBtn.removeAttribute("disabled");
      submitBtn.removeAttribute("aria-disabled");
    }
    let solvedOk = false;
    let running = null;
    let failCount = 0;
    let lastDifficulty = 0;
    let replayingSubmit = false;

    const run = async (force, options) => {
      const opts = options || {};
      if (solvedOk && !force) {
        return true;
      }

      if (running) {
        return running;
      }

      running = (async () => {
        if (force) {
          solvedOk = false;
          clearProof(form);
          syncElementorMirrorFields(form, ctx);
        }
        setHoneypotRequiredMode(form, true);
        ui.setState("working", t("working", "Sicherheitspruefung laeuft im Hintergrund..."));
        ui.setActionsVisible(false);

        try {
          const challenge = await fetchChallenge(ctx, !!opts.refreshRetry, form);
          if (!challenge || !challenge.token) {
            failCount += 1;
            ui.setState("error", t("challenge_error", "Challenge konnte nicht geladen werden."));
            ui.setActionsVisible(true, () => run(true, { refreshRetry: true }));
            return false;
          }

          lastDifficulty = Number(challenge.difficulty || 4);
          ui.setMeta(lastDifficulty, !!challenge.refresh_relief);
          const parts = challenge.token.split(".");
          const payloadEncoded = parts[0];
          const solved = await solve(payloadEncoded, Number(challenge.difficulty || 4));
          if (!solved || !solved.ok) {
            failCount += 1;
            const isHard = lastDifficulty >= 5;
            ui.setState(
              "error",
              isHard
                ? t("solve_retry_hard", "Pruefung aktuell sehr streng. Bitte Refresh-Symbol nutzen.")
                : t("solve_retry", "Pruefung nicht geloest. Bitte erneut absenden.")
            );
            if (failCount === 1 || isHard) {
              ui.setActionsVisible(true, () => run(true, { refreshRetry: true }));
            }
            return false;
          }

          form.querySelector('input[name="wpsh_pow"]').value = challenge.token;
          form.querySelector('input[name="wpsh_ctr"]').value = String(solved.counter);
          form.querySelector('input[name="wpsh_hash"]').value = solved.hash || "";
          syncElementorMirrorFields(form, ctx);

          solvedOk = true;
          failCount = 0;
          ui.setActionsVisible(false);
          ui.setState("ok", formatSolved(Number(solved.tookMs || 0)));
          return true;
        } catch (e) {
          failCount += 1;
          ui.setState("error", t("solve_reload", "Pruefung fehlgeschlagen. Bitte neu laden."));
          ui.setActionsVisible(true, () => run(true, { refreshRetry: true }));
          return false;
        } finally {
          running = null;
        }
      })();

      return running;
    };

    form.addEventListener(
      "focusin",
      () => {
        run();
      },
      { once: true }
    );

    form.addEventListener("submit", async (event) => {
      syncElementorMirrorFields(form, ctx);
      if (replayingSubmit || solvedOk) {
        return;
      }

      event.preventDefault();
      const submitter = event.submitter || document.activeElement || null;
      const ok = await run(false, { lockSubmit: false });
      syncElementorMirrorFields(form, ctx);
      if (!ok) {
        return;
      }

      replayingSubmit = true;
      resubmitForm(form, submitter);
    }, true);

    form.addEventListener("touchstart", () => syncElementorMirrorFields(form, ctx), true);
    form.addEventListener("pointerdown", () => syncElementorMirrorFields(form, ctx), true);
    form.addEventListener("click", (event) => {
      const target = event.target && event.target.closest ? event.target.closest('button[type="submit"], input[type="submit"]') : null;
      if (target && form.contains(target)) {
        syncElementorMirrorFields(form, ctx);
      }
    }, true);
  }

  function scanDocument(root) {
    const scope = root && root.querySelectorAll ? root : document;

    cfg.contexts.forEach((entry) => {
      const forms = collectMatchingForms(scope, entry.selector);
      forms.forEach((form) => attach(form, entry.ctx || "form"));
    });

    attachCommentFallback(scope);
  }

  function collectMatchingForms(scope, selector) {
    const result = [];

    if (scope.matches && scope.matches(selector)) {
      result.push(scope);
    }

    scope.querySelectorAll(selector).forEach((node) => result.push(node));
    return result;
  }

  function attachCommentFallback(scope) {
    collectMatchingForms(scope, 'form').forEach((form) => {
      const hasCommentField = !!form.querySelector('textarea[name="comment"]');
      const postsToComments = /wp-comments-post\.php/i.test(form.getAttribute("action") || "");
      if ((hasCommentField || postsToComments) && !form.querySelector('input[name="wpsh_ctx"]')) {
        attach(form, "comment");
      }
    });
  }

  function observeDynamicForms() {
    if (typeof MutationObserver !== "function") {
      return;
    }

    const observer = new MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        mutation.addedNodes.forEach((node) => {
          if (!node || node.nodeType !== 1) {
            return;
          }
          scanDocument(node);
        });
      });
    });

    observer.observe(document.documentElement || document.body, {
      childList: true,
      subtree: true,
    });
  }

  function installLazyFormHooks() {
    const ensureAttachedFromEvent = (event) => {
      const target = event && event.target;
      if (!target || !target.closest) {
        return;
      }
      const form = target.closest("form");
      if (!form) {
        return;
      }
      scanDocument(form);
    };

    document.addEventListener("focusin", ensureAttachedFromEvent, true);
    document.addEventListener("submit", ensureAttachedFromEvent, true);
  }

  function mergeConfig(base, extra) {
    const a = base && typeof base === "object" ? base : {};
    const b = extra && typeof extra === "object" ? extra : {};
    const aContexts = Array.isArray(a.contexts) ? a.contexts : [];
    const bContexts = Array.isArray(b.contexts) ? b.contexts : [];

    return {
      ...a,
      ...b,
      messages: { ...(a.messages || {}), ...(b.messages || {}) },
      branding: { ...(a.branding || {}), ...(b.branding || {}) },
      contexts: [...aContexts, ...bContexts],
      autoProtect: { ...(a.autoProtect || {}), ...(b.autoProtect || {}) },
    };
  }

  function normalizeAutoProtectConfig(raw) {
    const value = raw && typeof raw === "object" ? raw : {};
    return {
      enabled: !!value.enabled,
      ajaxActions: Array.isArray(value.ajaxActions) ? value.ajaxActions.filter(Boolean) : [],
      restRoutes: Array.isArray(value.restRoutes) ? value.restRoutes.filter(Boolean) : [],
      excludeUrls: Array.isArray(value.excludeUrls) ? value.excludeUrls.filter(Boolean) : [],
    };
  }

  function installAutoEndpointProtection() {
    patchFetch();
    patchXhr();
  }

  function installFormPayloadHooks() {
    patchFormDataConstructor();
    patchJQueryAjax();
    patchFormFetchPayloads();
    patchFormXhrPayloads();
  }

  function patchFormDataConstructor() {
    if (typeof window.FormData !== "function" || window.FormData.__wpshPatched === true) {
      return;
    }

    const NativeFormData = window.FormData;
    const WrappedFormData = function (form) {
      const data = arguments.length > 0 ? new NativeFormData(form) : new NativeFormData();
      if (isProtectedForm(form)) {
        applyFormProofToPayload(data, form);
      }
      return data;
    };

    WrappedFormData.prototype = NativeFormData.prototype;
    WrappedFormData.__wpshPatched = true;
    WrappedFormData.__wpshNative = NativeFormData;
    window.FormData = WrappedFormData;
  }

  function patchFormFetchPayloads() {
    if (typeof window.fetch !== "function" || window.fetch.__wpshFormPatched === true) {
      return;
    }

    const originalFetch = window.fetch.bind(window);
    const wrappedFetch = function (input, init) {
      const body = init && Object.prototype.hasOwnProperty.call(init, "body") ? init.body : null;
      const form = findProtectedFormForPayload(body);
      if (form) {
        applyFormProofToPayload(body, form);
      }

      return originalFetch(input, init);
    };

    wrappedFetch.__wpshFormPatched = true;
    window.fetch = wrappedFetch;
  }

  function patchFormXhrPayloads() {
    if (typeof XMLHttpRequest === "undefined") {
      return;
    }

    const proto = XMLHttpRequest.prototype;
    if (proto.__wpshFormPatched === true) {
      return;
    }

    const originalSend = proto.send;
    proto.send = function (body) {
      const form = findProtectedFormForPayload(body);
      if (form) {
        applyFormProofToPayload(body, form);
      }
      return originalSend.call(this, body);
    };

    proto.__wpshFormPatched = true;
  }

  function patchJQueryAjax() {
    const jq = window.jQuery || window.$;
    if (!jq || typeof jq.ajax !== "function" || jq.ajax.__wpshPatched === true) {
      return;
    }

    const originalAjax = jq.ajax;
    jq.ajax = function (url, options) {
      const settings = typeof url === "object" ? url : (options || {});
      if (settings && settings.data) {
        const form = findProtectedFormForPayload(settings.data);
        if (form) {
          settings.data = applyFormProofToPayload(settings.data, form);
        }
      }
      return originalAjax.apply(this, arguments);
    };
    jq.ajax.__wpshPatched = true;
  }

  function patchFetch() {
    if (typeof window.fetch !== "function" || window.fetch.__wpshPatched === true) {
      return;
    }

    const originalFetch = window.fetch.bind(window);
    const wrappedFetch = async function (input, init) {
      const plan = await buildAutoProtectPlanFromFetch(input, init);
      if (!plan) {
        return originalFetch(input, init);
      }

      const proof = await requestProof(plan.ctx);
      if (!proof) {
        return originalFetch(input, init);
      }

      if (input instanceof Request) {
        const nextHeaders = new Headers(input.headers || {});
        applyProofHeaders(nextHeaders, proof);
        if (!init) {
          const nextRequest = new Request(input, { headers: nextHeaders });
          return originalFetch(nextRequest);
        }

        const nextInit = { ...init, headers: nextHeaders };
        return originalFetch(input, nextInit);
      }

      const nextInit = { ...(init || {}) };
      const nextHeaders = new Headers(nextInit.headers || {});
      applyProofHeaders(nextHeaders, proof);
      nextInit.headers = nextHeaders;
      return originalFetch(input, nextInit);
    };

    wrappedFetch.__wpshPatched = true;
    window.fetch = wrappedFetch;
  }

  function patchXhr() {
    if (typeof XMLHttpRequest === "undefined") {
      return;
    }

    const proto = XMLHttpRequest.prototype;
    if (proto.__wpshPatched === true) {
      return;
    }

    const originalOpen = proto.open;
    const originalSend = proto.send;

    proto.open = function (method, url, async) {
      this.__wpshMeta = {
        method: method,
        url: url,
        async: async !== false,
      };
      return originalOpen.apply(this, arguments);
    };

    proto.send = function (body) {
      const meta = this.__wpshMeta || {};
      if (meta.async === false) {
        return originalSend.call(this, body);
      }

      const xhr = this;
      buildAutoProtectPlan(meta.method, meta.url, body).then(async (plan) => {
        if (!plan) {
          originalSend.call(xhr, body);
          return;
        }

        const proof = await requestProof(plan.ctx);
        if (!proof) {
          originalSend.call(xhr, body);
          return;
        }

        xhr.setRequestHeader("X-WPSH-Pow", proof.token);
        xhr.setRequestHeader("X-WPSH-Ctr", String(proof.counter));
        xhr.setRequestHeader("X-WPSH-Hash", proof.hash || "");
        xhr.setRequestHeader("X-WPSH-Ctx", plan.ctx);
        originalSend.call(xhr, body);
      }).catch(() => {
        originalSend.call(xhr, body);
      });

      return;
    };

    proto.__wpshPatched = true;
  }

  async function buildAutoProtectPlanFromFetch(input, init) {
    const req = input instanceof Request ? input : null;
    const method = ((init && init.method) || (req && req.method) || "GET");
    const url = (typeof input === "string" || input instanceof URL) ? String(input) : (req ? req.url : "");
    let body = init && Object.prototype.hasOwnProperty.call(init, "body") ? init.body : null;
    if (body == null && req) {
      body = await extractBodyFromRequest(req);
    }
    return buildAutoProtectPlan(method, url, body);
  }

  async function extractBodyFromRequest(req) {
    try {
      const clone = req.clone();
      const contentType = (clone.headers && clone.headers.get("content-type")) || "";
      if (/application\/x-www-form-urlencoded/i.test(contentType)) {
        return await clone.text();
      }
      if (/multipart\/form-data/i.test(contentType)) {
        return await clone.formData();
      }
    } catch (_e) {
      return null;
    }
    return null;
  }

  async function buildAutoProtectPlan(methodRaw, urlRaw, body) {
    if (!autoProtectCfg.enabled) {
      return null;
    }

    const method = String(methodRaw || "GET").toUpperCase();
    if (!["POST", "PUT", "PATCH", "DELETE"].includes(method)) {
      return null;
    }

    let url;
    try {
      url = new URL(String(urlRaw || ""), window.location.href);
    } catch (_e) {
      return null;
    }

    if (url.origin !== window.location.origin) {
      return null;
    }

    if (isChallengeEndpoint(url.href)) {
      return null;
    }

    if (isExcludedUrl(url)) {
      return null;
    }

    const ajaxCtx = deriveAjaxContext(url, body);
    if (ajaxCtx) {
      return { ctx: ajaxCtx };
    }

    const restCtx = deriveRestContext(url);
    if (restCtx) {
      return { ctx: restCtx };
    }

    return null;
  }

  function sameUrl(a, b) {
    try {
      return new URL(a, window.location.href).href === new URL(b, window.location.href).href;
    } catch (_e) {
      return false;
    }
  }

  function isChallengeEndpoint(url) {
    return challengeEndpointCandidates.some((candidate) => sameUrl(url, candidate));
  }

  function buildChallengeEndpoints(restUrl) {
    const endpoints = [];
    const seen = new Set();

    const push = (value) => {
      if (typeof value !== "string" || value.trim() === "") {
        return;
      }
      try {
        const href = new URL(value, window.location.href).href;
        if (seen.has(href)) {
          return;
        }
        seen.add(href);
        endpoints.push(href);
      } catch (_e) {
        // Ignore invalid endpoint variants.
      }
    };

    push(restUrl);

    let primary = null;
    try {
      primary = new URL(String(restUrl || ""), window.location.href);
    } catch (_e) {
      primary = null;
    }

    const defaultRoute = "/wpshield/v1/challenge";
    if (!primary) {
      push("/wp-json" + defaultRoute);
      push("/?rest_route=" + encodeURIComponent(defaultRoute));
      push("/index.php?rest_route=" + encodeURIComponent(defaultRoute));
      return endpoints;
    }

    let route = normalizeChallengeRoute(primary.searchParams.get("rest_route") || defaultRoute);
    let basePath = "/";

    const wpJsonMarker = "/wp-json/";
    const wpJsonIndex = primary.pathname.indexOf(wpJsonMarker);
    if (wpJsonIndex >= 0) {
      basePath = primary.pathname.slice(0, wpJsonIndex + 1);
      const routeFromPath = primary.pathname.slice(wpJsonIndex + "/wp-json".length);
      if (routeFromPath.startsWith("/")) {
        route = normalizeChallengeRoute(routeFromPath);
      }
    } else if (/\/index\.php$/i.test(primary.pathname)) {
      basePath = primary.pathname.replace(/index\.php$/i, "");
    }

    const normalizedBasePath = ensureTrailingSlash(basePath);
    const root = new URL(primary.origin);
    root.pathname = normalizedBasePath;
    root.search = "";
    root.hash = "";

    const pretty = new URL(root.href);
    pretty.pathname = normalizePath(normalizedBasePath + "wp-json" + route);
    push(pretty.href);

    const query = new URL(root.href);
    query.searchParams.set("rest_route", route);
    push(query.href);

    const indexQuery = new URL(root.href);
    indexQuery.pathname = normalizePath(normalizedBasePath + "index.php");
    indexQuery.searchParams.set("rest_route", route);
    push(indexQuery.href);

    return endpoints;
  }

  function normalizeChallengeRoute(routeRaw) {
    const value = typeof routeRaw === "string" ? routeRaw.trim() : "";
    const route = value !== "" ? value : "/wpshield/v1/challenge";
    const withSlash = route.startsWith("/") ? route : ("/" + route);
    const compact = withSlash.replace(/\/{2,}/g, "/").replace(/\/+$/, "");
    return compact || "/wpshield/v1/challenge";
  }

  function normalizePath(pathRaw) {
    const value = typeof pathRaw === "string" && pathRaw !== "" ? pathRaw : "/";
    const withSlash = value.startsWith("/") ? value : ("/" + value);
    return withSlash.replace(/\/{2,}/g, "/");
  }

  function ensureTrailingSlash(pathRaw) {
    const normalized = normalizePath(pathRaw);
    return normalized.endsWith("/") ? normalized : (normalized + "/");
  }

  function isExcludedUrl(url) {
    const path = url.pathname || "/";
    return autoProtectCfg.excludeUrls.some((pattern) => matchPattern(path, pattern));
  }

  function deriveAjaxContext(url, body) {
    const path = (url.pathname || "").toLowerCase();
    if (!/\/wp-admin\/admin-ajax\.php$/.test(path)) {
      return null;
    }

    const fromQuery = url.searchParams.get("action");
    const action = normalizeAjaxAction(fromQuery || extractActionFromBody(body));
    if (!action) {
      return null;
    }

    if (!autoProtectCfg.ajaxActions.includes(action)) {
      return null;
    }

    return "ajax:" + action;
  }

  function deriveRestContext(url) {
    const prefix = "/wp-json/";
    if (!url.pathname.startsWith(prefix)) {
      return null;
    }

    const route = "/" + url.pathname.slice(prefix.length);
    if (route === "/wpshield/v1/challenge" || route === "/wpshield/v1/verify") {
      return null;
    }

    const matched = autoProtectCfg.restRoutes.some((pattern) => matchPattern(route, pattern));
    if (!matched) {
      return null;
    }

    return "rest:" + route;
  }

  function normalizeAjaxAction(value) {
    if (typeof value !== "string") {
      return "";
    }
    return value.trim().toLowerCase().replace(/[^a-z0-9_-]/g, "");
  }

  function extractActionFromBody(body) {
    if (!body) {
      return "";
    }

    if (body instanceof URLSearchParams) {
      return body.get("action") || "";
    }

    if (typeof FormData !== "undefined" && body instanceof FormData) {
      const val = body.get("action");
      return typeof val === "string" ? val : "";
    }

    if (typeof body === "string") {
      try {
        const params = new URLSearchParams(body);
        return params.get("action") || "";
      } catch (_e) {
        return "";
      }
    }

    return "";
  }

  function matchPattern(value, pattern) {
    if (!pattern) {
      return false;
    }
    if (pattern.endsWith("*")) {
      return value.startsWith(pattern.slice(0, -1));
    }
    return value === pattern;
  }

  function applyProofHeaders(headers, proof) {
    headers.set("X-WPSH-Pow", proof.token);
    headers.set("X-WPSH-Ctr", String(proof.counter));
    headers.set("X-WPSH-Hash", proof.hash || "");
    headers.set("X-WPSH-Ctx", proof.ctx);
  }

  async function requestProof(ctx) {
    try {
      const challenge = await fetchChallenge(ctx, false, null);
      if (!challenge || !challenge.token) {
        return null;
      }

      const parts = String(challenge.token).split(".");
      const payloadEncoded = parts[0];
      const solved = await solve(payloadEncoded, Number(challenge.difficulty || 4));
      if (!solved || !solved.ok) {
        return null;
      }

      return {
        ctx,
        token: challenge.token,
        counter: solved.counter,
        hash: solved.hash || "",
      };
    } catch (_e) {
      return null;
    }
  }

  function ensureHidden(form, name) {
    let field = form.querySelector(`input[name="${name}"]`);
    if (!field) {
      field = document.createElement("input");
      field.type = "hidden";
      field.name = name;
      field.value = "";
      form.appendChild(field);
    }
    return field;
  }

  function ensureHoneypot(form) {
    const known = honeypotState.get(form);
    if (known && known.field) {
      return known.field;
    }

    const profile = selectHoneypotProfile(form);
    const trapName = profile.name;

    let trap = getInputByExactName(form, trapName);
    if (!trap) {
      trap = document.createElement("input");
      trap.type = "text";
      trap.name = trapName;
      trap.value = "";
      trap.autocomplete = "new-password";
      trap.autocapitalize = "none";
      trap.spellcheck = false;
      trap.inputMode = "none";
      trap.tabIndex = -1;
      trap.setAttribute("aria-label", profile.label);
      trap.setAttribute("aria-hidden", "true");
      trap.setAttribute("placeholder", profile.placeholder);
      trap.setAttribute("data-required", "1");
      trap.style.position = "absolute";
      trap.style.left = "-10000px";
      trap.style.top = "auto";
      trap.style.width = "1px";
      trap.style.height = "1px";
      trap.style.opacity = "0";
      trap.style.pointerEvents = "none";
      form.appendChild(trap);
    }
    honeypotState.set(form, { field: trap, profile });
    return trap;
  }

  function isProtectedForm(form) {
    return !!(form && form.tagName && String(form.tagName).toLowerCase() === "form" && form.dataset && form.dataset.wpshAttached === "1");
  }

  function findProtectedFormForPayload(payload) {
    if (!payload) {
      return null;
    }

    if (payload instanceof HTMLFormElement && isProtectedForm(payload)) {
      return payload;
    }

    if (typeof FormData !== "undefined" && payload instanceof FormData) {
      const ctx = payload.get("wpsh_ctx") || payload.get("form_fields[wpsh_ctx]") || "";
      return findProtectedFormByContext(String(ctx || "")) || findProtectedFormByAjaxAction(extractActionFromBody(payload));
    }

    if (payload instanceof URLSearchParams) {
      const ctx = payload.get("wpsh_ctx") || payload.get("form_fields[wpsh_ctx]") || "";
      return findProtectedFormByContext(String(ctx || "")) || findProtectedFormByAjaxAction(extractActionFromBody(payload));
    }

    if (typeof payload === "string") {
      try {
        const params = new URLSearchParams(payload);
        const ctx = params.get("wpsh_ctx") || params.get("form_fields[wpsh_ctx]") || "";
        return findProtectedFormByContext(String(ctx || "")) || findProtectedFormByAjaxAction(params.get("action") || "");
      } catch (_e) {
        return null;
      }
    }

    return null;
  }

  function findProtectedFormByContext(ctx) {
    if (!ctx || !ctx.startsWith("form:")) {
      return null;
    }

    const forms = Array.from(document.querySelectorAll("form[data-wpsh-attached='1']"));
    return forms.find((form) => {
      const field = getInputByExactName(form, "wpsh_ctx");
      return field && String(field.value || "") === ctx;
    }) || null;
  }

  function findProtectedFormByAjaxAction(action) {
    const elementorAction = "elementor" + "_pro_forms_send_form";
    if (String(action || "") !== elementorAction) {
      return null;
    }

    const forms = Array.from(document.querySelectorAll("form.elementor-form[data-wpsh-attached='1']"));
    return forms.length === 1 ? forms[0] : null;
  }

  function applyFormProofToPayload(payload, form) {
    if (!payload || !isProtectedForm(form)) {
      return payload;
    }

    const ctx = getFieldValue(form, "wpsh_ctx");
    syncElementorMirrorFields(form, ctx);

    const pairs = formProofPairs(form);
    if (typeof FormData !== "undefined" && payload instanceof FormData) {
      pairs.forEach(([name, value]) => setPayloadValue(payload, name, value));
      return payload;
    }

    if (payload instanceof URLSearchParams) {
      pairs.forEach(([name, value]) => payload.set(name, value));
      return payload;
    }

    if (typeof payload === "string") {
      try {
        const params = new URLSearchParams(payload);
        pairs.forEach(([name, value]) => params.set(name, value));
        return params.toString();
      } catch (_e) {
        return payload;
      }
    }

    return payload;
  }

  function formProofPairs(form) {
    const base = [
      ["wpsh_pow", getFieldValue(form, "wpsh_pow")],
      ["wpsh_ctr", getFieldValue(form, "wpsh_ctr")],
      ["wpsh_hash", getFieldValue(form, "wpsh_hash")],
      ["wpsh_ctx", getFieldValue(form, "wpsh_ctx")],
      ["wpsh_required", getFieldValue(form, "wpsh_required") || "1"],
    ];

    const pairs = [...base];
    if (isElementorForm(form, getFieldValue(form, "wpsh_ctx"))) {
      base.forEach(([name, value]) => pairs.push(["form_fields[" + name + "]", value]));
    }
    return pairs;
  }

  function getFieldValue(form, name) {
    const field = getInputByExactName(form, name);
    return field ? String(field.value || "") : "";
  }

  function setPayloadValue(payload, name, value) {
    if (typeof payload.set === "function") {
      payload.set(name, value);
      return;
    }
    if (typeof payload.append === "function") {
      payload.append(name, value);
    }
  }

  function setHoneypotRequiredMode(form, requiredMode) {
    const known = honeypotState.get(form);
    const trap = known && known.field ? known.field : null;
    if (!trap) return;
    const label = known && known.profile ? known.profile.label : "Address line 2";
    const placeholder = known && known.profile ? known.profile.placeholder : "Address line 2 *";
    trap.setAttribute("aria-label", label);
    if (requiredMode) {
      trap.setAttribute("data-required", "1");
      trap.setAttribute("placeholder", placeholder);
      return;
    }
    trap.setAttribute("data-required", "0");
    trap.setAttribute("placeholder", label);
  }

  function getHoneypotName(form) {
    if (!form) {
      return "";
    }
    const known = honeypotState.get(form);
    if (!known || !known.field || typeof known.field.name !== "string") {
      return "";
    }
    return String(known.field.name || "");
  }

  function selectHoneypotProfile(form) {
    const profiles = [
      { name: "address_line2", label: "Address line 2", placeholder: "Address line 2 *" },
      { name: "contact_fax", label: "Fax number", placeholder: "Fax number *" },
      { name: "company_website", label: "Company website", placeholder: "Company website *" },
      { name: "middle_name", label: "Middle name", placeholder: "Middle name *" },
      { name: "secondary_phone", label: "Secondary phone", placeholder: "Secondary phone *" },
      { name: "vat_number", label: "VAT number", placeholder: "VAT number *" },
      { name: "department_code", label: "Department code", placeholder: "Department code *" },
      { name: "office_extension", label: "Office extension", placeholder: "Office extension *" }
    ];
    const used = new Set();
    Array.from(form.elements || []).forEach((el) => {
      if (el && typeof el.name === "string" && el.name.trim() !== "") {
        used.add(el.name.trim().toLowerCase());
      }
    });
    for (const profile of profiles) {
      if (!used.has(profile.name.toLowerCase())) {
        return profile;
      }
    }
    return profiles[0];
  }

  function clearProof(form) {
    form.querySelector('input[name="wpsh_pow"]').value = "";
    form.querySelector('input[name="wpsh_ctr"]').value = "";
    form.querySelector('input[name="wpsh_hash"]').value = "";
  }

  function isElementorForm(form, ctx) {
    if (ctx !== "form:elementor") {
      return false;
    }
    if (!form || !form.matches) {
      return false;
    }
    return form.matches("form.elementor-form");
  }

  function getInputByExactName(form, name) {
    if (!form || !form.elements) {
      return null;
    }
    const elements = Array.from(form.elements || []);
    for (const el of elements) {
      if (el && typeof el.name === "string" && el.name === name) {
        return el;
      }
    }
    return null;
  }

  function ensureElementorMirrorField(form, name) {
    let field = getInputByExactName(form, name);
    if (!field) {
      field = document.createElement("input");
      field.type = "hidden";
      field.name = name;
      field.className = "elementor-field";
      form.appendChild(field);
    }
    return field;
  }

  function syncElementorMirrorFields(form, ctx) {
    if (!isElementorForm(form, ctx)) {
      return;
    }

    const mapping = [
      ["wpsh_pow", "form_fields[wpsh_pow]"],
      ["wpsh_ctr", "form_fields[wpsh_ctr]"],
      ["wpsh_hash", "form_fields[wpsh_hash]"],
      ["wpsh_ctx", "form_fields[wpsh_ctx]"],
      ["wpsh_required", "form_fields[wpsh_required]"],
    ];

    mapping.forEach(([sourceName, mirrorName]) => {
      const source = getInputByExactName(form, sourceName);
      if (!source) {
        return;
      }
      const mirror = ensureElementorMirrorField(form, mirrorName);
      mirror.value = String(source.value || "");
    });
  }

  async function fetchChallenge(ctx, refreshRetry, formRef) {
    const hpn = getHoneypotName(formRef);
    const payload = JSON.stringify({
      ctx,
      refresh_retry: refreshRetry ? 1 : 0,
      hpn: hpn,
    });

    for (const endpoint of challengeEndpointCandidates) {
      const first = await postChallengeRequest(endpoint, payload, "");
      if (first.ok) {
        return first.data;
      }

      if ((first.code === "rest_cookie_invalid_nonce" || first.code === "rest_forbidden") && cfg.restNonce) {
        const retryWithNonce = await postChallengeRequest(endpoint, payload, cfg.restNonce);
        if (retryWithNonce.ok) {
          return retryWithNonce.data;
        }
      }
    }
    return null;
  }

  async function postChallengeRequest(url, payload, nonce) {
    const headers = {
      "Content-Type": "application/json",
    };
    if (nonce) {
      headers["X-WP-Nonce"] = nonce;
    }

    try {
      const res = await fetch(url, {
        method: "POST",
        headers,
        body: payload,
        credentials: "same-origin",
        cache: "no-store",
      });

      if (!res.ok) {
        const errorPayload = await readJsonSafe(res);
        return {
          ok: false,
          code: errorPayload && typeof errorPayload.code === "string" ? errorPayload.code : "",
        };
      }

      const data = await readJsonSafe(res);
      if (!data || typeof data !== "object") {
        return { ok: false, code: "invalid_json" };
      }
      return { ok: true, data };
    } catch (_e) {
      return { ok: false, code: "network_error" };
    }
  }

  async function readJsonSafe(response) {
    try {
      return await response.clone().json();
    } catch (_e) {
      return null;
    }
  }

  function createStatusUI(form, ctx) {
    const box = document.createElement("div");
    box.className = "wpsh-status wpsh-status--idle";
    box.setAttribute("role", "status");
    box.setAttribute("aria-live", "polite");

    const title = document.createElement("p");
    title.className = "wpsh-status__title";

    const dot = document.createElement("span");
    dot.className = "wpsh-status__dot";
    dot.setAttribute("aria-hidden", "true");
    title.appendChild(dot);

    if (cfg.branding && cfg.branding.logoUrl) {
      const logo = document.createElement("img");
      logo.className = "wpsh-status__logo";
      logo.src = cfg.branding.logoUrl;
      logo.alt = "";
      logo.setAttribute("aria-hidden", "true");
      title.appendChild(logo);
    }

    title.appendChild(document.createTextNode("ProofShield"));

    const text = document.createElement("p");
    text.className = "wpsh-status__text";
    text.textContent = formatPreflight(labelForCtx(ctx));

    const meta = document.createElement("p");
    meta.className = "wpsh-status__meta";

    const bar = document.createElement("div");
    bar.className = "wpsh-status__bar";
    const barInner = document.createElement("span");
    bar.appendChild(barInner);

    const actions = document.createElement("div");
    actions.className = "wpsh-status__actions";
    const refresh = document.createElement("button");
    refresh.type = "button";
    refresh.className = "wpsh-refresh-btn";
    refresh.setAttribute("aria-label", t("btn_refresh", "Refresh"));
    refresh.setAttribute("title", t("btn_refresh", "Refresh"));
    refresh.innerHTML = '<span class="wpsh-refresh-btn__icon" aria-hidden="true">&#8635;</span><span class="wpsh-refresh-btn__label"></span>';
    const refreshLabel = refresh.querySelector(".wpsh-refresh-btn__label");
    if (refreshLabel) {
      refreshLabel.textContent = t("btn_refresh", "Refresh");
    }
    actions.appendChild(refresh);

    box.appendChild(title);
    box.appendChild(text);
    if (showDebugUi) {
      box.appendChild(meta);
    }
    box.appendChild(bar);
    box.appendChild(actions);

    const submit = form.querySelector('button[type="submit"], input[type="submit"]');
    if (submit && submit.parentNode) {
      submit.parentNode.insertBefore(box, submit);
    } else {
      form.appendChild(box);
    }

    return {
      setState: (state, message) => {
        box.className = "wpsh-status wpsh-status--" + state;
        text.textContent = message;
      },
      setMeta: (difficulty, refreshRelief) => {
        if (!showDebugUi) {
          return;
        }
        const chunks = [];
        const numericDifficulty = Number(difficulty || 0);
        if (numericDifficulty > 0) {
          chunks.push(t("difficulty_now", "Difficulty") + ": " + String(numericDifficulty));
        }
        if (refreshRelief) {
          chunks.push(t("refresh_relief", "Refresh relief active"));
        }
        meta.textContent = chunks.join(" | ");
        meta.style.display = meta.textContent ? "block" : "none";
      },
      setActionsVisible: (show, onRetry) => {
        actions.classList.toggle("wpsh-status__actions--visible", !!show);
        setHoneypotRequiredMode(form, !show);
        refresh.onclick = show && typeof onRetry === "function"
          ? async () => {
              refresh.classList.add("is-spinning");
              try {
                await onRetry();
              } finally {
                setTimeout(() => refresh.classList.remove("is-spinning"), 700);
              }
            }
          : null;
      },
    };
  }

  function setSubmitState(button, enabled) {
    // Intentionally no-op: ProofShield should not hard-disable submit controls in JS mode.
    void button;
    void enabled;
  }

  function resubmitForm(form, submitter) {
    if (typeof form.requestSubmit === "function") {
      if (isSubmitControlForForm(form, submitter)) {
        form.requestSubmit(submitter);
        return;
      }
      form.requestSubmit();
      return;
    }

    if (isSubmitControlForForm(form, submitter) && typeof submitter.click === "function") {
      submitter.click();
      return;
    }

    if (typeof form.submit === "function") {
      form.submit();
    }
  }

  function isSubmitControlForForm(form, node) {
    if (!node || !node.tagName) {
      return false;
    }
    const tag = String(node.tagName || "").toLowerCase();
    const type = String(node.type || "").toLowerCase();
    if (tag !== "button" && tag !== "input") {
      return false;
    }
    if (type && type !== "submit" && type !== "image") {
      return false;
    }
    return node.form === form || form.contains(node);
  }

  function labelForCtx(ctx) {
    if (ctx === "login") {
      return t("ctx_login", "Login");
    }

    if (ctx === "comment") {
      return t("ctx_comment", "Kommentar");
    }

    return t("ctx_form", "Formular");
  }

  function t(key, fallback) {
    const value = i18n[key];
    return typeof value === "string" && value !== "" ? value : fallback;
  }

  function formatSolved(ms) {
    const tpl = t("solved", "Geschuetzt. Nachweis erstellt in %d ms.");
    return tpl.replace("%d", String(ms));
  }

  function formatPreflight(ctxLabel) {
    const tpl = t("preflight", "%s: Pruefung wird beim Ausfuellen vorbereitet.");
    return tpl.replace("%s", ctxLabel);
  }

  function solve(payloadEncoded, difficulty) {
    return new Promise((resolve) => {
      const workerUrl = cfg.workerUrl || null;

      if (!workerUrl) {
        resolve({ ok: false, reason: "worker_missing" });
        return;
      }

      const worker = new Worker(workerUrl);
      worker.onmessage = (event) => {
        resolve(event.data || { ok: false });
        worker.terminate();
      };
      worker.onerror = () => {
        resolve({ ok: false, reason: "worker_error" });
        worker.terminate();
      };
      worker.postMessage({
        payload: payloadEncoded,
        difficulty,
        maxMs: 2500 + Math.max(0, Number(difficulty || 0)) * 900,
      });
    });
  }

})();
