/**
 * otpAuditLogger.js
 * OTP Testing & Automation Framework — Audit Logger
 *
 * FOR DEV / STAGING / QA / ACCESSIBILITY TESTING ONLY.
 *
 * Logs all OTP-related events with timestamps, context, and results.
 * Redacts sensitive values. Stores in chrome.storage.local with rotation.
 * Max 200 entries (FIFO).
 */
(function initVisaFlowXOtpAuditLogger(global) {
  "use strict";

  const AUDIT_KEY  = "vfx.otp.audit";
  const MAX_ENTRIES = 200;

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

  function hasChromeStorage() {
    return Boolean(typeof chrome !== "undefined" && chrome?.storage?.local);
  }

  function redact(value) {
    if (typeof value !== "string") return value;
    if (value.length <= 2) return "**";
    return value[0] + "*".repeat(value.length - 2) + value[value.length - 1];
  }

  function buildEntry(event, meta = {}) {
    return {
      event,
      at:     new Date().toISOString(),
      url:    typeof location !== "undefined" ? location.href : "",
      ...meta
    };
  }

  // ── In-memory log (always available) ─────────────────────────
  const _memLog = [];

  // ── Persistent log ───────────────────────────────────────────
  async function _persistEntry(entry) {
    if (!hasChromeStorage()) return;
    try {
      const result = await chrome.storage.local.get(AUDIT_KEY);
      const existing = Array.isArray(result[AUDIT_KEY]) ? result[AUDIT_KEY] : [];
      const updated  = [...existing, entry].slice(-MAX_ENTRIES);
      await chrome.storage.local.set({ [AUDIT_KEY]: updated });
    } catch (_) {}
  }

  /**
   * Log an OTP audit event.
   * @param {string}  event  Event name, e.g. "OTP_DETECTED", "OTP_ENTERED"
   * @param {object}  meta   Additional context (sensitive values are redacted)
   */
  function auditLog(event, meta = {}) {
    const sanitized = { ...meta };
    // Redact any field that looks like a code/token/password
    for (const key of Object.keys(sanitized)) {
      if (/code|token|otp|pin|secret|password/i.test(key)) {
        sanitized[key] = redact(String(sanitized[key] || ""));
      }
    }

    const entry = buildEntry(event, sanitized);
    _memLog.push(entry);
    if (_memLog.length > MAX_ENTRIES) _memLog.shift();

    // Print to console (dev-friendly)
    console.log(`[VisaFlowX][Audit] ${event}`, entry);

    // Async persist (fire-and-forget)
    _persistEntry(entry).catch(() => {});

    return entry;
  }

  /**
   * Read all stored audit entries.
   * @returns {Promise<object[]>}
   */
  async function getAuditLog() {
    if (hasChromeStorage()) {
      const result = await chrome.storage.local.get(AUDIT_KEY).catch(() => ({}));
      return Array.isArray(result[AUDIT_KEY]) ? result[AUDIT_KEY] : [..._memLog];
    }
    return [..._memLog];
  }

  /**
   * Clear the persistent audit log.
   */
  async function clearAuditLog() {
    _memLog.length = 0;
    if (hasChromeStorage()) {
      await chrome.storage.local.remove(AUDIT_KEY).catch(() => {});
    }
    log("Audit log cleared");
  }

  const OtpAuditLogger = Object.freeze({ log: auditLog, getAuditLog, clearAuditLog });

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

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