/**
 * otpTestProvider.js
 * OTP Testing & Automation Framework — Test OTP Provider
 *
 * FOR DEV / STAGING / QA / ACCESSIBILITY TESTING ONLY.
 * *** DISABLED IN PRODUCTION AUTOMATICALLY ***
 *
 * Provides deterministic, expiring OTP codes for local test environments.
 * Never intercepts real SMS/email OTPs. Never contacts external services.
 */
(function initVisaFlowXOtpTestProvider(global) {
  "use strict";

  // ── Environment gate ─────────────────────────────────────────
  // Returns true ONLY when running in a recognized dev/staging/QA origin.
  const ALLOWED_ORIGINS = new Set([
    "localhost",
    "127.0.0.1",
    "0.0.0.0",
    "staging",
    "dev",
    "test",
    "qa"
  ]);

  function isTestEnvironment() {
    if (typeof location === "undefined") return false;
    const host = location.hostname || "";
    return (
      host === "localhost" ||
      host === "127.0.0.1" ||
      host.startsWith("192.168.") ||
      host.startsWith("10.") ||
      ALLOWED_ORIGINS.has(host) ||
      /\.(local|test|dev|staging|qa)$/.test(host)
    );
  }

  function log(msg) {
    console.log("[VisaFlowX][OtpTestProvider]", msg);
  }

  // ── Internal store ───────────────────────────────────────────
  const _store = new Map();

  // ── TOTP-style 6-digit OTP generation ───────────────────────
  // Uses a simple time-window algorithm (NOT TOTP crypto, just for testing).
  function _generateCode(length = 6, expiryMs = 60000) {
    const digits  = Math.floor(Math.random() * Math.pow(10, length))
      .toString()
      .padStart(length, "0");
    const expiresAt = Date.now() + expiryMs;
    return { code: digits, expiresAt };
  }

  /**
   * Generate a test OTP.
   * @param {object} options { length: 6, expiryMs: 60000, context: "login" }
   * @returns {{ code, expiresAt, context }} — audit logged.
   */
  function generateTestOtp(options = {}) {
    if (!isTestEnvironment()) {
      throw new Error("[OtpTestProvider] generateTestOtp() is disabled in production environments.");
    }

    const length   = Number(options.length   || 6);
    const expiryMs = Number(options.expiryMs || 60000);
    const context  = String(options.context  || "default");

    const entry = { ..._generateCode(length, expiryMs), context };
    _store.set(context, entry);

    OtpAuditLogger?.log("OTP_GENERATED", { context, expiresAt: entry.expiresAt });
    log(`Test OTP generated for context "${context}"`);

    return { code: entry.code, expiresAt: entry.expiresAt, context };
  }

  /**
   * Validate a test OTP.
   * @param {string} code     The code to validate.
   * @param {string} context  The context key.
   */
  function validateTestOtp(code, context = "default") {
    if (!isTestEnvironment()) {
      return { valid: false, reason: "production_disabled" };
    }

    const entry = _store.get(context);
    if (!entry) {
      OtpAuditLogger?.log("OTP_VALIDATION_FAILED", { context, reason: "no_code_generated" });
      return { valid: false, reason: "no_code_generated" };
    }
    if (Date.now() > entry.expiresAt) {
      _store.delete(context);
      OtpAuditLogger?.log("OTP_VALIDATION_FAILED", { context, reason: "expired" });
      return { valid: false, reason: "expired" };
    }
    if (entry.code !== String(code)) {
      OtpAuditLogger?.log("OTP_VALIDATION_FAILED", { context, reason: "wrong_code" });
      return { valid: false, reason: "wrong_code" };
    }

    _store.delete(context); // One-time use
    OtpAuditLogger?.log("OTP_VALIDATED", { context });
    log(`Test OTP validated successfully for context "${context}"`);
    return { valid: true, context };
  }

  // ── Audit logger reference (loaded separately) ───────────────
  const OtpAuditLogger = null; // Will be set by otpAuditLogger.js if loaded

  const OtpTestProvider = Object.freeze({
    isTestEnvironment,
    generateTestOtp,
    validateTestOtp
  });

  global.VisaFlowX = Object.assign(global.VisaFlowX || {}, {
    OtpTestProvider,
    generateTestOtp: generateTestOtp,
    validateTestOtp: validateTestOtp
  });

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