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

  const DEFAULTS = Object.freeze({
    cooldownMs: () => 45000 + Math.random() * 30000,
    duplicateWindowMs: 2500,
    maxRetryCount: 5,
    staleMs: 10 * 60 * 1000
  });

  function now() {
    return Date.now();
  }

  function cleanTabId(tabId) {
    const value = Number(tabId);
    return Number.isFinite(value) && value >= 0 ? value : null;
  }

  function signature(details = {}) {
    return [
      details.source || "",
      details.selector || "",
      details.url || ""
    ].join("|");
  }

  function createRecord(at) {
    return {
      active: false,
      firstSeenAt: 0,
      lastSeenAt: 0,
      lastResolvedAt: 0,
      lastSignature: "",
      retryCount: 0,
      retryWindowStartedAt: at,
      cooldownUntil: 0,
      details: {}
    };
  }

  function nextCooldownMs(config) {
    const value = typeof config.cooldownMs === "function" ? config.cooldownMs() : config.cooldownMs;
    return Math.max(45000, Math.min(75000, Number(value) || 60000));
  }

  function createManager(options = {}) {
    const config = { ...DEFAULTS, ...options };
    const records = new Map();

    function get(tabId) {
      const id = cleanTabId(tabId);
      if (id === null) return null;
      if (!records.has(id)) records.set(id, createRecord(now()));
      return records.get(id);
    }

    function cleanupExpired() {
      const at = now();
      for (const [tabId, record] of records) {
        const lastActivity = Math.max(record.lastSeenAt, record.lastResolvedAt, record.firstSeenAt);
        if (!record.active && lastActivity && at - lastActivity > config.staleMs) {
          records.delete(tabId);
        }
      }
    }

    function markDetected(tabId, details = {}) {
      cleanupExpired();
      const record = get(tabId);
      if (!record) return { ok: false, reason: "missing_tab" };

      const at = now();
      const currentSignature = signature(details);
      const firstSeen = !record.active;
      const duplicate = record.active
        && record.lastSignature === currentSignature
        && at - record.lastSeenAt < config.duplicateWindowMs;

      if (at - record.retryWindowStartedAt > config.cooldownMs) {
        record.retryWindowStartedAt = at;
        record.retryCount = 0;
      }

      if (firstSeen) {
        record.firstSeenAt = at;
        record.retryCount += 1;
      }

      const limited = record.retryCount > config.maxRetryCount;
      if (limited) record.cooldownUntil = Math.max(record.cooldownUntil, at + nextCooldownMs(config));

      record.active = true;
      record.lastSeenAt = at;
      record.lastSignature = currentSignature;
      record.details = { ...details };

      return {
        ok: true,
        active: true,
        firstSeen,
        duplicate,
        limited,
        retryCount: record.retryCount,
        retryAfterMs: Math.max(0, record.cooldownUntil - at),
        snapshot: snapshot(tabId)
      };
    }

    function markResolved(tabId, details = {}) {
      cleanupExpired();
      const record = get(tabId);
      if (!record) return { ok: false, reason: "missing_tab" };

      const at = now();
      const wasActive = record.active;
      const duplicate = !wasActive && at - record.lastResolvedAt < config.duplicateWindowMs;

      record.active = false;
      record.lastResolvedAt = at;
      record.lastSignature = signature(details);
      record.details = { ...details };

      return {
        ok: true,
        active: false,
        wasActive,
        duplicate,
        retryCount: record.retryCount,
        snapshot: snapshot(tabId)
      };
    }

    function snapshot(tabId) {
      const record = records.get(cleanTabId(tabId));
      if (!record) return null;
      return {
        active: record.active,
        firstSeenAt: record.firstSeenAt,
        lastSeenAt: record.lastSeenAt,
        lastResolvedAt: record.lastResolvedAt,
        retryCount: record.retryCount,
        cooldownUntil: record.cooldownUntil,
        details: { ...record.details }
      };
    }

    function isActive(tabId) {
      return records.get(cleanTabId(tabId))?.active === true;
    }

    function clear(tabId) {
      const id = cleanTabId(tabId);
      if (id !== null) records.delete(id);
    }

    function clearAll() {
      records.clear();
    }

    return Object.freeze({
      clear,
      clearAll,
      isActive,
      markDetected,
      markResolved,
      snapshot
    });
  }

  const ChallengeState = Object.freeze({
    DEFAULTS,
    createManager
  });

  global.VisaFlowX = Object.assign(global.VisaFlowX || {}, { ChallengeState });

  if (typeof module !== "undefined" && module.exports) {
    module.exports = ChallengeState;
  }
})(typeof globalThis !== "undefined" ? globalThis : this);
