// ============================================
// FP SCOUT v6 — debug.js
// Lightweight diagnostic logger for background, sidepanel and content scripts.
// ============================================

(function initFPDebug(global) {
  if (global.FPDebug) return;

  const ENABLED_KEY = 'debugEnabled';
  const LOG_KEY = 'debugLog';
  const MAX_EVENTS = 800;
  const FLUSH_DELAY_MS = 1200;
  const SENSITIVE_KEY_RE = /(token|secret|password|passwd|api.?key|apikey|license|auth|captcha|signature|cookie|session|bearer)/i;
  const LICENSE_RE = /\bFPS-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}\b/gi;
  const LONG_SECRET_RE = /\b[A-Za-z0-9_-]{24,}\b/g;

  let pendingEvents = [];
  let flushTimer = null;
  let flushPromise = null;

  const hasChromeStorage = () => !!(global.chrome && chrome.storage && chrome.storage.local);

  function cloneSanitized(value, depth = 0) {
    if (depth > 6) return '[max-depth]';
    if (value == null) return value;
    if (typeof value === 'string') {
      return value
        .replace(LICENSE_RE, '[redacted-license]')
        .replace(LONG_SECRET_RE, token => token.length > 32 ? '[redacted-token]' : token);
    }
    if (typeof value === 'number' || typeof value === 'boolean') return value;
    if (value instanceof Error) {
      return { name: value.name, message: value.message, stack: value.stack };
    }
    if (Array.isArray(value)) return value.slice(0, 50).map(v => cloneSanitized(v, depth + 1));
    if (typeof value === 'object') {
      const out = {};
      for (const [key, val] of Object.entries(value).slice(0, 80)) {
        out[key] = SENSITIVE_KEY_RE.test(key) ? '[redacted]' : cloneSanitized(val, depth + 1);
      }
      return out;
    }
    return String(value);
  }

  function storageGet(keys) {
    if (!hasChromeStorage()) return Promise.resolve({});
    return chrome.storage.local.get(keys);
  }

  function storageSet(data) {
    if (!hasChromeStorage()) return Promise.resolve();
    return chrome.storage.local.set(data);
  }

  async function isEnabled() {
    try {
      const data = await storageGet(ENABLED_KEY);
      return !!data[ENABLED_KEY];
    } catch (e) {
      return false;
    }
  }

  async function setEnabled(enabled) {
    await storageSet({ [ENABLED_KEY]: !!enabled });
    if (enabled) await log('debug.enabled', { enabled: true }, { force: true });
    if (!enabled) await flush();
  }

  function contextName() {
    if (typeof location !== 'undefined' && /(^|\.)farpost\.ru$/.test(location.hostname || '')) return 'content';
    if (typeof ServiceWorkerGlobalScope !== 'undefined' && global instanceof ServiceWorkerGlobalScope) return 'background';
    if (typeof location !== 'undefined' && location.href?.startsWith('chrome-extension://')) return 'extension-page';
    return 'unknown';
  }

  function makeEvent(event, payload) {
    return {
      ts: new Date().toISOString(),
      context: contextName(),
      event,
      payload: cloneSanitized(payload),
    };
  }

  function scheduleFlush() {
    if (flushTimer) return;
    flushTimer = setTimeout(() => {
      flushTimer = null;
      flush();
    }, FLUSH_DELAY_MS);
  }

  async function flush() {
    if (flushPromise) return flushPromise;
    flushPromise = (async () => {
      if (flushTimer) {
        clearTimeout(flushTimer);
        flushTimer = null;
      }
      if (!pendingEvents.length) return;
      const batch = pendingEvents.splice(0, pendingEvents.length);
      const data = await storageGet(LOG_KEY);
      const events = Array.isArray(data[LOG_KEY]) ? data[LOG_KEY] : [];
      await storageSet({ [LOG_KEY]: events.concat(batch).slice(-MAX_EVENTS) });
    })().catch(() => {
      // Debug must never break product code.
    }).finally(() => {
      flushPromise = null;
      if (pendingEvents.length) scheduleFlush();
    });
    return flushPromise;
  }

  async function log(event, payload = {}, options = {}) {
    try {
      if (!options.force && !(await isEnabled())) return;
      pendingEvents.push(makeEvent(event, payload));
      if (pendingEvents.length > MAX_EVENTS) pendingEvents = pendingEvents.slice(-MAX_EVENTS);
      if (options.force) await flush();
      else scheduleFlush();
    } catch (e) {
      // Debug must never break product code.
    }
  }

  async function clear() {
    pendingEvents = [];
    if (flushTimer) {
      clearTimeout(flushTimer);
      flushTimer = null;
    }
    await storageSet({ [LOG_KEY]: [] });
  }

  async function getReport(extra = {}) {
    await flush();
    const data = await storageGet([LOG_KEY, ENABLED_KEY]);
    const manifest = global.chrome?.runtime?.getManifest ? chrome.runtime.getManifest() : {};
    return {
      exportedAt: new Date().toISOString(),
      enabled: !!data[ENABLED_KEY],
      extension: {
        name: manifest.name || 'FP Scout',
        version: manifest.version || '',
      },
      browser: typeof navigator !== 'undefined' ? navigator.userAgent : '',
      currentUrl: typeof location !== 'undefined' ? location.href : '',
      extra: cloneSanitized(extra),
      events: Array.isArray(data[LOG_KEY]) ? data[LOG_KEY] : [],
    };
  }

  global.FPDebug = {
    log,
    clear,
    isEnabled,
    setEnabled,
    getReport,
    flush,
    sanitize: cloneSanitized,
  };
})(globalThis);
