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

  const { Detector, DomUtils, NotificationHandler } = global.VisaFlowX;
  const ACTIVE_STATES = new Set([
    "RUNNING", "WAITING_VERIFICATION", "WAITING_COOLDOWN",
    "WAITING_RETRY", "SERVER_COOLDOWN", "RETRYING", "RELOADING", "ERROR"
  ]);
  const TRIGGER_DEDUPE_MS = 10000;
  let lastTriggerAt  = 0;
  let watcher        = null;
  let watcherTimer   = null;
  let watcherSettings = {};

  // ── OTP PRIORITY: When OTP page appears, IMMEDIATELY: ────────
  //   1. Stop all running automation tasks
  //   2. Pause scheduler / retry engine / login attempts
  //   3. Set state = OTP_REQUIRED / OTP_DETECTED
  //   4. trigger forcePlayOtpAlarm — continue until dismissed
  // ─────────────────────────────────────────────────────────────

  async function trigger(pageState, settings = {}) {
    const otp = pageState?.otp || Detector.detectOtp(document);
    if (!otp?.present) return { ok: true, skipped: true, reason: "otp_not_present" };

    const now = Date.now();
    if (now - lastTriggerAt < TRIGGER_DEDUPE_MS) {
      return { ok: true, skipped: true, reason: "otp_recently_triggered", otp };
    }
    lastTriggerAt = now;
    stopWatching();

    // ── Focus + highlight the OTP input ─────────────────────────
    if (otp.input) {
      DomUtils.focusElement(otp.input);
      DomUtils.pulseHighlight(otp.input, true);
    }

    // ── Signal background: OTP_DETECTED (locks automation) ──────
    let signalPromise = Promise.resolve({ ok: true, skipped: true });
    if (chrome?.runtime?.sendMessage) {
      signalPromise = chrome.runtime.sendMessage({
        type:   "OTP_DETECTED",
        reason: otp.reason || "otp_page",
        url:    location.href
      }).catch((error) => ({ ok: false, error: error?.message || String(error || "signal_failed") }));
    }

    // Retrieve settings
    const state = await chrome.runtime.sendMessage({ type: "GET_STATE" }).catch(() => null);
    const activeSettings = { ...settings, ...(state?.settings || {}) };

    // ── OTP ALARM: use forcePlayOtpAlarm (safe, with fallback) ──
    let alarmPromise = Promise.resolve({ ok: true, skipped: true });
    if (activeSettings.soundEnabled !== false) {
      alarmPromise = NotificationHandler.forcePlayOtpAlarm({
        volume: activeSettings.volume ?? 1,
        muted:  activeSettings.alarmMuted === true
      }).then((result) => {
        if (!result.ok && result.blocked) {
          console.log(
            "[VisaFlowX][OtpMonitor]",
            "Audio pending until user interaction.",
            "Using fallback notification until audio is enabled."
          );
        }
        return result;
      }).catch((error) => {
        console.warn("[VisaFlowX][OtpMonitor] OTP alarm error (non-fatal):", error?.message || error);
        return { ok: false, error: error?.message || String(error || "alarm_failed") };
      });
    }

    const [alarm, signal] = await Promise.allSettled([alarmPromise, signalPromise]);

    return {
      ok:     true,
      otp,
      alarm:  alarm.status  === "fulfilled" ? alarm["value"]  : { ok: false, error: alarm.reason?.message  || String(alarm.reason  || "") },
      signal: signal.status === "fulfilled" ? signal["value"] : { ok: false, error: signal.reason?.message || String(signal.reason || "") }
    };
  }

  async function shouldAutoTrigger() {
    if (!chrome?.runtime?.sendMessage) return false;
    const state  = await chrome.runtime.sendMessage({ type: "GET_STATE" }).catch(() => null);
    const status = state?.status || {};
    return ACTIVE_STATES.has(status.state || "") || status.otpState === "Detected";
  }

  function scheduleWatch() {
    if (watcherTimer) clearTimeout(watcherTimer);
    watcherTimer = setTimeout(async () => {
      watcherTimer = null;
      const otp = Detector.detectOtp(document);
      if (!otp.present) return;
      if (!await shouldAutoTrigger()) return;
      await trigger({ otp }, watcherSettings).catch(() => {});
    }, 30);
  }

  function startWatching(settings = {}) {
    watcherSettings = settings || {};
    if (watcher) {
      scheduleWatch();
      return;
    }
    const target = document.documentElement || document.body;
    if (!target) return;
    watcher = new MutationObserver(scheduleWatch);
    watcher.observe(target, {
      childList:      true,
      subtree:        true,
      characterData:  true,
      attributes:     true,
      attributeFilter: ["autocomplete", "class", "id", "name", "placeholder", "style", "type", "value"]
    });
    window.addEventListener("pagehide", stopWatching, { once: true });
    scheduleWatch();
  }

  function stopWatching() {
    if (watcher) watcher.disconnect();
    watcher = null;
    if (watcherTimer) clearTimeout(watcherTimer);
    watcherTimer = null;
  }

  function reset() {
    lastTriggerAt = 0;
  }

  const OtpMonitor = Object.freeze({ reset, startWatching, stopWatching, trigger });
  global.VisaFlowX = Object.assign(global.VisaFlowX || {}, { OtpMonitor });
})(typeof globalThis !== "undefined" ? globalThis : this);
