// PhishProtect Background Script - Enterprise Edition
// Integrates analyzer engine, policy management, telemetry, and enterprise features

// Core modules
import { AnalyzerEngine } from './core/analyzer-engine.js';
import { RuleRegistry } from './core/rule-registry.js';
import { ConfigManager } from './core/config-manager.js';
import { StatsCollector } from './core/stats-collector.js';

// Policy modules
import { PolicyEngine } from './policies/policy-engine.js';
import { PolicyManager } from './policies/policy-manager.js';
import { AuditLogger } from './policies/audit-logger.js';

// Telemetry modules
import { TelemetryCollector } from './telemetry/telemetry-collector.js';
import { PrivacyFilter } from './telemetry/privacy-filter.js';

// Dynamic rule updater
import { DynamicRuleUpdater } from './core/dynamic-rule-updater.js';

// Detection reporting & cloud analysis
import { DetectionReporter } from './telemetry/detection-reporter.js';
import { CloudQueryClient } from './cloud/cloud-query-client.js';

// Dynamic toolbar icon
import { updateIcon } from './core/icon-manager.js';

// v3: Signal-based architecture
import { SignalProviderRegistry } from './core/signal-provider.js';
import { FeatureStore } from './core/feature-store.js';
import { registerClipboardInjectionSignals } from './detectors/data-theft/clipboard-injection-signals.js';
import { registerClipboardPoisoningSignals } from './detectors/data-theft/clipboard-poisoning-signals.js';
import { registerCommandPatternSignals } from './detectors/social-engineering/command-pattern-signals.js';
import { registerDialogTrapSignals } from './detectors/social-engineering/dialog-trap-signals.js';

// Evidence gathering modules
import { HeaderCapture } from './evidence/header-capture.js';
import { FrameChainBuilder } from './evidence/frame-chain-builder.js';

// Enterprise modules
import { MDMIntegration } from './enterprise/mdm-integration.js';
import { AdminConsoleConnector } from './enterprise/admin-console-connector.js';
import { SIEMReporter } from './enterprise/siem-reporter.js';
import { ClickHouseReporter } from './enterprise/clickhouse-reporter.js';

// AI Visibility
import { AIVisibilityReporter } from './ai-visibility/ai-visibility-reporter.js';
import { matchAIDomain } from './ai-visibility/ai-domains.js';
import { IdentityManager } from './ai-visibility/identity-manager.js';
import { ContentDetector } from './ai-visibility/content-detector.js';

// Global instances
let analyzerEngine;
let ruleRegistry;
let configManager;
let statsCollector;
let policyManager;
let auditLogger;
let telemetryCollector;
let privacyFilter;
let mdmIntegration;
let adminConsole;
let siemReporter;
let clickhouseReporter;
let dynamicRuleUpdater;
let detectionReporter;
let cloudQueryClient;
let headerCapture;
let frameChainBuilder;
let signalProviderRegistry;
let featureStore;
let aiVisibilityReporter;
let identityManager;
let contentDetector;

// Extension state
let extensionState = {
  enabled: true,
  initialized: false,
  detectorCount: 0,
  activePolicy: 'default'
};

// Statistics (backward compatibility with old popup.js)
let stats = {
  blockedUrls: 0,
  suspiciousResources: 0,
  permissionRequests: 0,
  clipboardAlerts: 0,
  httpsUpgrades: 0
};

// Store last detection for blocked page
let lastDetection = null;

// Per-tab accumulated detection state (populated by analyzeUrlRequest, clipboard handlers, etc.)
// Map<tabId, { url, detections: [], riskScore, riskLevel, decision, timestamp }>
const tabDetections = new Map();

// Per-tab AI content detection results
// tabId → { textScans: [{verdict, confidence, ...}], imageScans: [{verdict, confidence, ...}] }
const tabContentScans = new Map();

/**
 * Derive icon state from tabDetections + URL for a given tab.
 * Lightweight sync function — no async chrome.tabs.get needed when url is passed in.
 */
function getTabIconState(tabId, url) {
  if (!extensionState.enabled) {
    return { security: 'disabled', findingsCount: 0, aiContent: 'unknown' };
  }

  const tabState = tabDetections.get(tabId);
  const isHttp = url?.startsWith('http://');
  const isHttps = url?.startsWith('https://');

  let security = 'unknown'; // non-web page (chrome://, about:, etc.)
  if (isHttps || isHttp) {
    if (tabState?.action === 'block' || tabState?.riskLevel === 'critical' || tabState?.riskLevel === 'high' || isHttp) {
      security = 'danger';
    } else if (tabState?.action === 'warn' || tabState?.riskLevel === 'medium') {
      security = 'warning';
    } else {
      security = 'safe';
    }
  }

  // Check if this tab is on an AI domain
  let aiContent = 'unknown';
  if (aiVisibilityReporter) {
    const aiInfo = aiVisibilityReporter.getTabAIInfo(tabId);
    if (aiInfo) aiContent = aiInfo.service;
  }

  // Count AI content detections (synthetic text/images flagged on this page)
  let aiContentCount = 0;
  const scans = tabContentScans.get(tabId);
  if (scans) {
    const flagged = (s) => {
      const v = s?.verdict;
      return v === 'ai_generated' || v === 'manipulated' || v === 'mixed';
    };
    aiContentCount = (scans.textScans || []).filter(flagged).length
                   + (scans.imageScans || []).filter(flagged).length;
    if (aiContentCount > 0) aiContent = aiContent === 'unknown' ? 'detected' : aiContent;
  }

  return {
    security,
    findingsCount: tabState?.findings?.length || 0,
    aiContent,
    aiContentCount
  };
}

/**
 * Update the toolbar icon for a tab. Accepts optional url to avoid async lookup.
 * If url is not provided, does an async chrome.tabs.get.
 */
async function updateTabIcon(tabId, url) {
  try {
    if (!url) {
      const tab = await chrome.tabs.get(tabId);
      url = tab.url || tab.pendingUrl || '';
    }
    const state = getTabIconState(tabId, url);
    await updateIcon(tabId, state);
  } catch (err) {
    // Tab may have been closed
    if (!err.message?.includes('No tab with id')) {
      console.error('updateTabIcon error:', err.message);
    }
  }
}

/**
 * Initialize PhishProtect extension
 */
async function initializeExtension() {
  console.log('Initializing PhishProtect Enterprise...');

  try {
    // Step 1: Load configuration
    configManager = new ConfigManager();
    await configManager.loadConfig();
    console.log('✓ Configuration loaded');

    // Step 2: Initialize rule registry
    ruleRegistry = new RuleRegistry(configManager.config);
    await ruleRegistry.loadAllRules();
    console.log('✓ Rules loaded');

    // Step 2a: Load v3 enhanced rulesets from local files
    const v3Rulesets = [
      { category: 'data-theft', subcategory: 'clipboard-injection', path: 'rules/v3/data-theft/clipboard-injection.json' },
      { category: 'data-theft', subcategory: 'clipboard-poisoning', path: 'rules/v3/data-theft/clipboard-poisoning.json' },
      { category: 'social-engineering', subcategory: 'command-pattern', path: 'rules/v3/social-engineering/command-pattern.json' },
      { category: 'social-engineering', subcategory: 'dialog-trap', path: 'rules/v3/social-engineering/dialog-trap.json' },
    ];
    for (const rs of v3Rulesets) {
      await ruleRegistry.loadRulesFromFile(rs.category, rs.subcategory, rs.path).catch(err => {
        console.warn(`Failed to load v3 ruleset ${rs.path}:`, err.message);
      });
    }
    console.log('✓ v3 rulesets loaded');

    // Step 2a-ii: Load v2 fingerprint rulesets
    const v2FingerprintRulesets = [
      { category: 'fingerprint', subcategory: 'web-servers', path: 'rules/v2/fingerprint/webservers.json' },
      { category: 'fingerprint', subcategory: 'cms', path: 'rules/v2/fingerprint/wordpress.json' },
    ];
    for (const rs of v2FingerprintRulesets) {
      await ruleRegistry.loadRulesFromFile(rs.category, rs.subcategory, rs.path).catch(err => {
        console.warn(`Failed to load v2 fingerprint ruleset ${rs.path}:`, err.message);
      });
    }
    console.log('✓ v2 fingerprint rulesets loaded');

    // Step 2b: Initialize dynamic rule updater
    dynamicRuleUpdater = new DynamicRuleUpdater(ruleRegistry, {
      ruleApiUrl: configManager.get('ruleApiUrl') || 'https://api.nithic.ai'
    });
    dynamicRuleUpdater.initialize().catch(error => {
      console.warn('Dynamic rule updater initialization failed (will use local rules):', error.message);
    });
    console.log('✓ Dynamic rule updater started');

    // Step 2c: Initialize v3 signal-based architecture
    featureStore = new FeatureStore();
    await featureStore.restore(); // Restore from session storage (survives SW restart)
    console.log('✓ FeatureStore initialized');

    signalProviderRegistry = new SignalProviderRegistry();
    registerClipboardInjectionSignals(signalProviderRegistry);
    registerClipboardPoisoningSignals(signalProviderRegistry);
    registerCommandPatternSignals(signalProviderRegistry);
    registerDialogTrapSignals(signalProviderRegistry);
    console.log(`✓ SignalProviderRegistry initialized (${signalProviderRegistry.getStats().registered} providers)`);

    // Step 3: Initialize analyzer engine
    analyzerEngine = new AnalyzerEngine(ruleRegistry, configManager.config);
    analyzerEngine.setFeatureStore(featureStore);
    analyzerEngine.setProviderRegistry(signalProviderRegistry);
    await analyzerEngine.initialize();
    console.log(`✓ Analyzer engine initialized with ${analyzerEngine.getDetectorCount()} detectors`);
    extensionState.detectorCount = analyzerEngine.getDetectorCount();

    // Step 4: Initialize policy management
    policyManager = new PolicyManager(configManager.config);
    await policyManager.initialize();
    extensionState.activePolicy = policyManager.getActivePolicyId();
    console.log(`✓ Policy manager initialized (active: ${extensionState.activePolicy})`);

    // Step 5: Initialize audit logger
    auditLogger = new AuditLogger(configManager.config);
    await auditLogger.initializeLogger();
    console.log('✓ Audit logger initialized');

    // Step 6: Initialize telemetry
    privacyFilter = new PrivacyFilter(configManager.config);
    telemetryCollector = new TelemetryCollector(configManager.config);
    console.log('✓ Telemetry collector initialized');

    // Step 7: Initialize statistics collector
    statsCollector = new StatsCollector(configManager.config);
    console.log('✓ Statistics collector initialized');

    // Step 7b: Generate or load persistent device ID
    const deviceId = await getOrCreateDeviceId();
    console.log(`✓ Device ID: ${deviceId}`);

    // Step 7c: Collect system context (browser, OS, extension config)
    const systemContext = await collectSystemContext();
    console.log(`✓ System context: ${systemContext.browser} on ${systemContext.os}`);

    // Step 7d: Initialize evidence gathering (header capture + frame chain builder)
    // Must be before detection reporter so frameChainBuilder is available at construction
    headerCapture = new HeaderCapture();
    headerCapture.initialize();
    frameChainBuilder = new FrameChainBuilder(headerCapture);
    await frameChainBuilder.initialize();
    console.log('✓ Evidence gathering initialized (header capture + frame chain)');

    // Step 7e: Initialize detection reporter (cloud telemetry)
    const reporterSettings = await loadCloudTelemetrySettings();
    const extensionVersion = chrome.runtime.getManifest().version;
    detectionReporter = new DetectionReporter({
      apiUrl: configManager.get('ruleApiUrl') || 'https://api.nithic.ai',
      enabled: reporterSettings.detectionReporting !== false,
      shareUrls: reporterSettings.shareUrls !== false,
      screenshotMode: reporterSettings.screenshotMode || 'full',
      deviceId: deviceId,
      extensionVersion: extensionVersion,
      systemContext: systemContext,
      frameChainBuilder: frameChainBuilder
    });
    console.log('✓ Detection reporter initialized');

    // Step 7f: Initialize AI Visibility Reporter
    aiVisibilityReporter = new AIVisibilityReporter({
      apiUrl: configManager.get('dashboardApiUrl') || 'https://api.portal.nithic.ai',
      enabled: true,
      deviceId: deviceId,
      extensionVersion: extensionVersion
    });

    // Step 7f-ii: Initialize Identity Manager
    identityManager = new IdentityManager({
      apiUrl: configManager.get('dashboardApiUrl') || 'https://api.portal.nithic.ai',
      enabled: true
    });

    // Step 7f-iii: Initialize Content Detector
    contentDetector = new ContentDetector({
      cloudUrl: reporterSettings.cloudAnalysisUrl || 'https://cloud.nithic.ai',
      dashboardUrl: configManager.get('dashboardApiUrl') || 'https://api.portal.nithic.ai',
      enabled: true,
      deviceId: deviceId
    });

    // Step 7g: Initialize cloud query client
    cloudQueryClient = new CloudQueryClient({
      cloudUrl: reporterSettings.cloudAnalysisUrl || 'https://cloud.nithic.ai',
      enabled: reporterSettings.cloudAnalysis || false,
      deviceId: deviceId,
      extensionVersion: extensionVersion
    });
    console.log('✓ Cloud query client initialized');

    // Step 8: Initialize enterprise integrations (if enabled)
    if (configManager.get('enterpriseMode')) {
      console.log('Enterprise mode enabled - initializing integrations...');

      // MDM Integration
      if (configManager.get('mdmEnabled')) {
        mdmIntegration = new MDMIntegration(configManager.config);
        await mdmIntegration.initialize();
        console.log('✓ MDM integration initialized');
      }

      // Admin Console
      if (configManager.get('adminConsoleEnabled')) {
        adminConsole = new AdminConsoleConnector(configManager.config);
        await adminConsole.initialize();
        console.log('✓ Admin console connector initialized');
      }

      // SIEM Reporter
      if (configManager.get('siemEnabled')) {
        siemReporter = new SIEMReporter(configManager.config);
        await siemReporter.initialize();
        console.log('✓ SIEM reporter initialized');
      }

      // ClickHouse Reporter
      if (configManager.get('clickhouseEnabled')) {
        clickhouseReporter = new ClickHouseReporter(configManager.config);
        await clickhouseReporter.initialize();
        console.log('✓ ClickHouse reporter initialized');
      }
    }

    // Step 9: Load legacy stats for backward compatibility
    await loadLegacyStats();

    extensionState.initialized = true;
    console.log('✅ PhishProtect Enterprise initialized successfully');

  } catch (error) {
    console.error('❌ Failed to initialize PhishProtect:', error);
    extensionState.initialized = false;
  }
}

/**
 * Load legacy stats from storage for backward compatibility
 */
async function loadLegacyStats() {
  return new Promise((resolve) => {
    chrome.storage.local.get(['stats'], (result) => {
      if (result.stats) {
        stats = result.stats;
        console.log('Loaded legacy stats from storage:', stats);
      }
      resolve();
    });
  });
}

/**
 * Load cloud telemetry settings from storage
 */
async function loadCloudTelemetrySettings() {
  return new Promise((resolve) => {
    chrome.storage.local.get(['cloudTelemetrySettings'], (result) => {
      resolve(result.cloudTelemetrySettings || {
        detectionReporting: true,
        shareUrls: true,
        screenshotMode: 'full',
        cloudAnalysis: false,
        cloudAnalysisUrl: 'https://cloud.nithic.ai'
      });
    });
  });
}

/**
 * Generate or load a persistent device ID (UUID stored in chrome.storage.local)
 */
async function getOrCreateDeviceId() {
  return new Promise((resolve) => {
    chrome.storage.local.get(['phishprotect_device_id'], (result) => {
      if (result.phishprotect_device_id) {
        resolve(result.phishprotect_device_id);
      } else {
        // Generate a new UUID
        const id = crypto.randomUUID();
        chrome.storage.local.set({ phishprotect_device_id: id }, () => {
          resolve(id);
        });
      }
    });
  });
}

/**
 * Collect system context: browser, OS, extension config
 */
async function collectSystemContext() {
  const manifest = chrome.runtime.getManifest();
  const platformInfo = await chrome.runtime.getPlatformInfo();

  // Parse user agent for browser info
  const ua = navigator.userAgent;
  let browser = 'Unknown';
  const chromeMatch = ua.match(/Chrome\/(\d+\.\d+\.\d+\.\d+)/);
  const edgeMatch = ua.match(/Edg\/(\d+\.\d+\.\d+\.\d+)/);
  const braveMatch = ua.match(/Brave\/(\d+)/);

  if (edgeMatch) {
    browser = `Edge ${edgeMatch[1]}`;
  } else if (braveMatch) {
    browser = `Brave`;
  } else if (chromeMatch) {
    browser = `Chrome ${chromeMatch[1]}`;
  }

  return {
    browser: browser,
    os: `${platformInfo.os} ${platformInfo.arch}`,
    platform: platformInfo.os,
    arch: platformInfo.arch,
    extension_version: manifest.version,
    extension_name: manifest.name,
    manifest_version: manifest.manifest_version,
    user_agent: ua
  };
}

/**
 * Save legacy stats to storage
 */
function saveLegacyStats() {
  chrome.storage.local.set({ stats }, () => {
    if (chrome.runtime.lastError) {
      console.error('Failed to save stats:', chrome.runtime.lastError);
    }
  });
}

/**
 * Notify popup of stats update
 */
function notifyStatsUpdate() {
  chrome.runtime.sendMessage({
    type: 'statsUpdated',
    data: stats
  }).catch(() => {
    // Ignore errors if popup is not open
  });
}

/**
 * Analyze URL request using new analyzer engine
 */
async function analyzeUrlRequest(details) {
  if (!extensionState.initialized || !extensionState.enabled) {
    return; // Non-blocking, no return value needed
  }

  const startTime = performance.now();

  try {
    // Analyze URL with analyzer engine
    const detection = await analyzerEngine.analyzeUrl(details.url, {
      tabId: details.tabId,
      frameId: details.frameId
    });

    // Record performance
    const latency = performance.now() - startTime;
    telemetryCollector.recordPerformance('url-analysis', latency, detection.matched);

    // Always store the latest analysis result for this tab (even clean ones)
    if (details.tabId && details.tabId !== -1) {
      const existing = tabDetections.get(details.tabId);
      if (!existing || detection.matched) {
        // For matched detections, accumulate findings; for clean, store baseline
        const prev = existing || { url: details.url, detections: [], findings: [], riskScore: 0, riskLevel: 'none', action: 'allow', timestamp: Date.now() };
        if (detection.matched) {
          prev.detections.push(detection);
          prev.findings = prev.findings.concat(detection.findings || []);
          if (detection.riskScore > prev.riskScore) {
            prev.riskScore = detection.riskScore;
            prev.riskLevel = detection.riskLevel;
          }
        }
        prev.url = details.url;
        prev.timestamp = Date.now();
        tabDetections.set(details.tabId, prev);
      }
    }

    if (!detection.matched) {
      return; // Non-blocking, no return value needed
    }

    // Evaluate policy
    const decision = policyManager.evaluateDetection(detection);

    // Store the policy action for this tab
    if (details.tabId && details.tabId !== -1) {
      const tabState = tabDetections.get(details.tabId);
      if (tabState) {
        const actionPriority = { block: 3, quarantine: 2, warn: 1, allow: 0 };
        if ((actionPriority[decision.action] || 0) > (actionPriority[tabState.action] || 0)) {
          tabState.action = decision.action;
        }
      }
    }

    // Update toolbar icon to reflect new detection state
    if (details.tabId && details.tabId !== -1) {
      updateTabIcon(details.tabId, details.url);
    }

    // Record telemetry
    telemetryCollector.recordDetection(detection, { tabId: details.tabId });
    telemetryCollector.recordAction(decision.action);

    // Record audit log
    await auditLogger.logDecision(decision, {
      policyId: policyManager.getActivePolicyId(),
      tabId: details.tabId
    });

    // Report to enterprise systems
    if (siemReporter) {
      await siemReporter.reportDetection(detection, { deviceId: configManager.get('deviceId') });
      await siemReporter.reportPolicyDecision(decision, { policyId: policyManager.getActivePolicyId() });
    }

    if (clickhouseReporter) {
      clickhouseReporter.reportDetection(detection, { deviceId: configManager.get('deviceId') });
      clickhouseReporter.reportPolicyDecision(decision, { policyId: policyManager.getActivePolicyId() });
    }

    // v3: Attach feature store snapshot to detection for cloud/telemetry
    if (featureStore && featureStore.hasTab(details.tabId)) {
      detection.features = featureStore.getSnapshot(details.tabId);
    }

    // Report ALL detections with findings to cloud telemetry
    if (detection.findings && detection.findings.length > 0) {
      console.log(`[Nithic] URL detection: ${detection.findings.length} finding(s) on ${details.url?.slice(0, 80)} - action=${decision.action} - reporter=${!!detectionReporter}`);
      if (detectionReporter) {
        detectionReporter.reportBlockingDetection(
          detection, decision, details.tabId, details.url, details.frameId || 0
        ).catch(err => {
          console.error('[Nithic] Detection reporter error:', err.message);
        });
      } else {
        console.warn('[Nithic] reportBlockingDetection skipped — reporter not initialized');
      }
    }

    // Handle policy action
    if (decision.action === 'block') {
      stats.blockedUrls++;
      saveLegacyStats();
      notifyStatsUpdate();

      // Store last detection for blocked page
      lastDetection = {
        url: details.url,
        detection,
        decision,
        timestamp: Date.now()
      };

      console.log('🚫 Blocked URL:', {
        riskScore: detection.riskScore,
        findingCount: detection.findings.length,
        action: decision.action
      });

      // Note: Actual blocking now done by declarativeNetRequest
      // This is just for logging/telemetry
    } else if (decision.action === 'warn') {
      // Show warning but allow
      chrome.tabs.sendMessage(details.tabId, {
        type: 'showWarning',
        data: {
          message: decision.enforcement.message,
          riskScore: detection.riskScore,
          findings: privacyFilter.filterDetection(detection)
        }
      }).catch(() => {});

      // For medium-risk / warn detections, query cloud analysis service
      if (cloudQueryClient && cloudQueryClient.shouldEscalate(detection, decision)) {
        cloudQueryClient.queryCloud(details.url, detection).then(cloudResult => {
          if (cloudResult.determination === 'malicious' && cloudResult.confidence > 0.7) {
            // Upgrade to block based on cloud analysis
            console.log('🔄 Cloud escalation: upgrading warn to block', cloudResult);
            stats.blockedUrls++;
            saveLegacyStats();
            notifyStatsUpdate();

            lastDetection = {
              url: details.url,
              detection,
              decision: { ...decision, action: 'block', cloudEscalated: true },
              timestamp: Date.now()
            };

            // Report escalated detection
            if (detectionReporter) {
              detectionReporter.reportBlockingDetection(
                detection, { ...decision, action: 'block', cloudEscalated: true },
                details.tabId, details.url, details.frameId || 0
              ).catch(() => {});
            }
          }
        }).catch(err => {
          console.error('Cloud query error:', err.message);
        });
      }
    }

  } catch (error) {
    console.error('Error analyzing URL:', error);
  }
}

/**
 * Analyze resource request
 */
async function analyzeResourceRequest(details) {
  if (!extensionState.initialized || !extensionState.enabled) {
    return; // Non-blocking
  }

  const startTime = performance.now();

  try {
    // Analyze resource
    const detection = await analyzerEngine.analyzeResource(details);

    // Record performance
    const latency = performance.now() - startTime;
    telemetryCollector.recordPerformance('resource-analysis', latency, detection.matched);

    if (!detection.matched) {
      return; // Non-blocking
    }

    // Evaluate policy
    const decision = policyManager.evaluateDetection(detection);

    // Record telemetry and audit
    telemetryCollector.recordDetection(detection, { tabId: details.tabId });
    telemetryCollector.recordAction(decision.action);
    await auditLogger.logDecision(decision, { policyId: policyManager.getActivePolicyId() });

    // Report to enterprise systems
    if (clickhouseReporter) {
      clickhouseReporter.reportDetection(detection);
      clickhouseReporter.reportPolicyDecision(decision);
    }

    // Handle policy action
    if (decision.action === 'block' || decision.action === 'quarantine') {
      stats.suspiciousResources++;
      saveLegacyStats();
      notifyStatsUpdate();

      console.log('🚫 Blocked resource:', {
        type: details.type,
        riskScore: detection.riskScore,
        action: decision.action
      });

      // Note: Actual blocking done by declarativeNetRequest
    }

  } catch (error) {
    console.error('Error analyzing resource:', error);
  }
}

/**
 * Handle permission addition
 */
async function handlePermissionAdd(permissions) {
  if (!extensionState.initialized || !extensionState.enabled) {
    return;
  }

  try {
    // Analyze permissions
    const detection = await analyzerEngine.analyzePermissions(permissions);

    if (!detection.matched) {
      return;
    }

    // Evaluate policy
    const decision = policyManager.evaluateDetection(detection);

    // Record telemetry and audit
    telemetryCollector.recordDetection(detection);
    telemetryCollector.recordAction(decision.action);
    await auditLogger.logDecision(decision, { policyId: policyManager.getActivePolicyId() });

    // Update stats
    stats.permissionRequests++;
    saveLegacyStats();
    notifyStatsUpdate();

    // Show warning if needed
    if (decision.action === 'warn' || decision.action === 'block') {
      console.warn('⚠️ Suspicious permissions detected:', {
        permissions: permissions.permissions,
        riskScore: detection.riskScore,
        action: decision.action
      });
    }

  } catch (error) {
    console.error('Error analyzing permissions:', error);
  }
}

/**
 * Handle messages from content scripts and popup
 */
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  // Legacy stats API (backward compatibility)
  if (message.type === 'getStats') {
    sendResponse(stats);
    return true;
  }

  // Legacy analysis API
  if (message.type === 'GET_ANALYSIS') {
    sendResponse({
      blockedUrls: stats.blockedUrls,
      suspiciousResources: stats.suspiciousResources,
      permissionRequests: stats.permissionRequests
    });
    return true;
  }

  // Identity detected from content script (login form, OAuth)
  if (message.type === 'identity_detected') {
    if (identityManager && message.data.identityDomain) {
      identityManager.setIdentity(
        message.data.site,
        message.data.identityDomain,
        message.data.method || 'form_login'
      );
    }
    return false;
  }

  // AI Visibility: policy check before allowing action
  if (message.type === 'ai_visibility_policy_check') {
    if (identityManager) {
      const result = identityManager.evaluatePolicy(
        message.data.aiService,
        message.data.action,
        message.data.siteDomain
      );
      sendResponse(result);
    } else {
      sendResponse({ allowed: true });
    }
    return true; // async sendResponse
  }

  // Content detection: scan text for AI generation
  if (message.type === 'content_scan_text') {
    const tabId = sender?.tab?.id;
    if (contentDetector) {
      contentDetector.analyzeText(message.data.text, {
        url: message.data.url,
        domain: message.data.domain,
        aiService: message.data.aiService
      }).then(result => {
        if (result) {
          // Store per-tab result
          if (tabId) {
            if (!tabContentScans.has(tabId)) tabContentScans.set(tabId, { textScans: [], imageScans: [] });
            const scans = tabContentScans.get(tabId);
            scans.textScans.push({
              verdict: result.cloud?.cloudVerdict || result.client?.verdict || 'uncertain',
              confidence: result.cloud?.cloudConfidence || result.client?.confidence || 0,
              timestamp: Date.now()
            });
            // Cap stored scans
            if (scans.textScans.length > 20) scans.textScans = scans.textScans.slice(-20);
            updateTabIcon(tabId).catch(() => {});
          }
          if (result.cloud) {
            console.log(`Content scan: text ${result.cloud.cloudVerdict} (${result.cloud.cloudConfidence})`);
          }
        }
        sendResponse(result);
      }).catch(e => {
        console.error('Content scan text error:', e);
        sendResponse(null);
      });
    } else {
      sendResponse(null);
    }
    return true; // async sendResponse
  }

  // Content detection: scan image for AI generation / deepfake / manipulation
  if (message.type === 'content_scan_image') {
    const tabId = sender?.tab?.id;
    if (contentDetector) {
      contentDetector.analyzeImage(message.data.imageData, {
        url: message.data.url,
        domain: message.data.domain,
        aiService: message.data.aiService
      }).then(result => {
        if (result) {
          // Store per-tab result
          if (tabId) {
            if (!tabContentScans.has(tabId)) tabContentScans.set(tabId, { textScans: [], imageScans: [] });
            const scans = tabContentScans.get(tabId);
            scans.imageScans.push({
              verdict: result.cloud?.cloudVerdict || result.client?.verdict || 'uncertain',
              confidence: result.cloud?.cloudConfidence || result.client?.confidence || 0,
              manipulationDetected: result.cloud?.manipulationDetected || false,
              manipulationType: result.cloud?.manipulationType || null,
              timestamp: Date.now()
            });
            if (scans.imageScans.length > 20) scans.imageScans = scans.imageScans.slice(-20);
            // Refresh badge: AI count may have changed
            updateTabIcon(tabId).catch(() => {});
          }
          if (result.cloud) {
            console.log(`Content scan: image ${result.cloud.cloudVerdict} (${result.cloud.cloudConfidence})${result.cloud.manipulationDetected ? ' [MANIPULATION]' : ''}`);
          }
        }
        sendResponse(result);
      }).catch(e => {
        console.error('Content scan image error:', e);
        sendResponse(null);
      });
    } else {
      sendResponse(null);
    }
    return true; // async sendResponse
  }

  // AI Visibility: user action on AI domain (enrich with identity)
  if (message.type === 'ai_visibility_event') {
    if (aiVisibilityReporter) {
      const eventData = { ...message.data };
      // Enrich with identity if available
      if (identityManager) {
        const identity = identityManager.getIdentityForHost(eventData.domain);
        if (identity) {
          eventData.identityDomain = identity.identityDomain;
          eventData.identityType = identity.identityType;
        }
      }
      aiVisibilityReporter.record(eventData);
    }
    return false;
  }

  // Clipboard alerts — clickfix-style copy/paste blocks
  // Build a detection event and report to telemetry so it shows up in the
  // portal's Hunting / Investigation pages (was previously dead-ending in stats).
  if (message.type === 'suspicious_copy' || message.type === 'suspicious_paste') {
    stats.clipboardAlerts++;
    saveLegacyStats();
    notifyStatsUpdate();

    const direction = message.type === 'suspicious_copy' ? 'copy' : 'paste';
    console.log(`[Nithic] Clipboard ${direction} blocked: pattern=${message.data?.patternId} host=${sender?.tab?.url ? new URL(sender.tab.url).host : '?'} reporter=${!!detectionReporter}`);
    if (detectionReporter && sender?.tab) {
      const tab = sender.tab;
      const data = message.data || {};
      const detection = {
        riskScore: 8,
        riskLevel: 'high',
        // rule_id is a varchar column on telemetry_events — string is fine.
        // pattern_id / technique_id are integer FKs, leave null (no matching rows yet).
        ruleId: data.patternId || ('clipboard-' + direction),
        findings: [{
          // Match the schema older clipboard-injection events used so the
          // portal's Hunting review panel renders the full evidence panel.
          type: data.patternName || ('Suspicious clipboard ' + direction),
          weight: 5,
          severity: 'critical',
          category: 'social-engineering',
          subcategory: 'command-pattern',
          detector: 'clipboard-monitor',
          rule_id: data.patternId || ('clipboard-' + direction),
          pattern: data.patternId || null,
          matched: data.patternName || null,
          description: 'Suspicious command pattern detected in clipboard (' + direction + ')',
          evidence: {
            threat_types: [data.patternName].filter(Boolean),
            clipboard_source: data.clipboardSource || 'user-' + direction,
            clipboard_content: data.fullText || data.textPreview || null,
            text_length: data.length || 0,
            page_url: data.pageUrl || tab.url,
            page_title: data.pageTitle || tab.title,
            page_host: data.pageHost || null,
            selection_type: data.selectionType || null,
            active_tag: data.activeTag || null,
            inline_scripts: data.inlineScripts || [],
            timestamp: data.timestamp || Date.now()
          }
        }],
        metadata: {
          detectorsRun: 1,
          detectorsMatched: 1,
          targetType: 'clipboard',
          latency: 0
        }
      };
      const decision = { action: 'block', reason: 'suspicious-clipboard-' + direction };
      detectionReporter.reportBlockingDetection(detection, decision, tab.id, tab.url, sender.frameId || 0)
        .catch(err => console.error('Clipboard telemetry error:', err.message));
    }
    return false;
  }

  // Clipboard injection blocked (from injected script)
  if (message.type === 'clipboard_injection_blocked') {
    stats.clipboardAlerts++;
    saveLegacyStats();
    notifyStatsUpdate();

    console.log('🚫 Clipboard injection blocked:', {
      threats: message.data.threats,
      source: message.data.source,
      timestamp: message.data.timestamp
    });

    // Record in telemetry for risk distribution
    const riskScore = message.data.threats.length * 5;
    const detection = {
      detector: 'clipboard-injection',
      matched: true,
      findings: message.data.threats.map(t => ({
        detector: 'clipboard-injection',
        type: t.type,
        severity: t.severity,
        weight: 5,
        category: 'data-theft'
      })),
      riskScore: riskScore,
      riskLevel: riskScore >= 15 ? 'critical' : riskScore >= 10 ? 'high' : riskScore >= 5 ? 'medium' : 'low',
      // Attach clipboard-specific evidence for telemetry
      clipboardEvidence: {
        source: message.data.source,
        contentPreview: message.data.contentPreview || null,
        threatTypes: message.data.threats.map(t => t.type),
        stackTrace: message.data.stackTrace || null,
        sourceSnippets: message.data.sourceSnippets || null,
        inlineScripts: message.data.inlineScripts || null,
        dynamicScripts: message.data.dynamicScripts || null
      }
    };

    // CVE escalation: boost risk score if site has known vulnerabilities
    const clipTabId = sender?.tab?.id;
    if (clipTabId) {
      const clipVulns = tabDetections.get(clipTabId)?.vulnerabilities;
      if (clipVulns?.summary?.critical > 0) {
        detection.riskScore = riskScore + 10;
        detection.riskLevel = detection.riskScore >= 15 ? 'critical' : detection.riskScore >= 10 ? 'high' : detection.riskScore >= 5 ? 'medium' : 'low';
        detection.cveEscalation = clipVulns.summary;
        detection.vulnerabilities = clipVulns.summary;
      } else if (clipVulns?.summary?.high > 0) {
        detection.riskScore = riskScore + 5;
        detection.riskLevel = detection.riskScore >= 15 ? 'critical' : detection.riskScore >= 10 ? 'high' : detection.riskScore >= 5 ? 'medium' : 'low';
        detection.cveEscalation = clipVulns.summary;
        detection.vulnerabilities = clipVulns.summary;
      }
    }

    // v3: Attach feature store snapshot for cloud/telemetry
    if (featureStore && clipTabId && featureStore.hasTab(clipTabId)) {
      detection.features = featureStore.getSnapshot(clipTabId);
    }

    // Store clipboard detection in per-tab state
    if (clipTabId) {
      const prev = tabDetections.get(clipTabId) || { url: sender?.tab?.url || '', detections: [], findings: [], riskScore: 0, riskLevel: 'none', action: 'allow', timestamp: Date.now() };
      prev.detections.push(detection);
      prev.findings = prev.findings.concat(detection.findings || []);
      if (riskScore > prev.riskScore) {
        prev.riskScore = riskScore;
        prev.riskLevel = detection.riskLevel;
      }
      prev.action = 'block';
      prev.timestamp = Date.now();
      tabDetections.set(clipTabId, prev);

      // Update toolbar icon to reflect clipboard threat
      updateTabIcon(clipTabId, sender?.tab?.url);
    }

    if (telemetryCollector) {
      telemetryCollector.recordDetection(detection, {
        source: message.data.source,
        timestamp: message.data.timestamp
      });
    }

    // Log to audit trail
    if (auditLogger) {
      const threatTypes = message.data.threats.map(t => t.type).join(', ');
      auditLogger.logUserAction('clipboard-injection-blocked', {
        threats: message.data.threats,
        source: message.data.source,
        timestamp: message.data.timestamp,
        threatSummary: threatTypes
      }).catch(error => {
        console.error('Failed to log clipboard injection block:', error);
      });
    }

    // Report to cloud telemetry
    if (detectionReporter) {
      const decision = { action: 'block', reason: 'clipboard-injection' };
      const tabUrl = sender?.tab?.url || sender?.url || null;
      detectionReporter.reportBlockingDetection(
        detection, decision, sender?.tab?.id, tabUrl, sender?.frameId || 0
      ).catch(error => {
        console.error('Failed to report clipboard detection:', error);
      });
    }

    // Report to enterprise systems
    if (siemReporter) {
      siemReporter.reportDetection(detection, {
        source: message.data.source,
        deviceId: configManager.get('deviceId')
      }).catch(error => {
        console.error('Failed to report clipboard injection to SIEM:', error);
      });
    }

    // Escalate LOLBin clipboard detections to cloud for real-time learning
    if (cloudQueryClient && cloudQueryClient.enabled) {
      const tabUrl = sender?.tab?.url || sender?.url || '';
      cloudQueryClient.queryCloud(tabUrl, detection, {
        source: 'clipboard',
        clipboardContent: message.data.contentPreview,
        threatTypes: message.data.threats.map(t => t.type)
      }).then(cloudResult => {
        console.log('Cloud clipboard analysis:', cloudResult);
      }).catch(err => {
        console.error('Cloud clipboard query error:', err.message);
      });
    }

    return false;
  }

  // False positive report (from user)
  if (message.type === 'false_positive_report') {
    console.log('📝 False positive report received:', {
      threats: message.data.threats,
      contentHash: message.data.contentHash,
      timestamp: message.data.timestamp
    });

    // Log to audit trail
    if (auditLogger) {
      const threatTypes = message.data.threats.map(t => t.type).join(', ');
      auditLogger.logUserAction('false-positive-report', {
        threats: message.data.threats,
        source: message.data.source,
        contentHash: message.data.contentHash,
        contentLength: message.data.contentLength,
        timestamp: message.data.timestamp,
        url: message.data.url,
        threatSummary: threatTypes
      }).catch(error => {
        console.error('Failed to log false positive report:', error);
      });
    }

    // Send to telemetry for analysis
    if (telemetryReporter && telemetryReporter.enabled) {
      telemetryReporter.reportDetection({
        detector: 'false-positive-report',
        matched: true,
        findings: [{
          detector: 'user-feedback',
          type: 'false-positive-report',
          severity: 'low',
          weight: 1,
          description: 'User reported false positive',
          metadata: {
            originalThreats: message.data.threats,
            contentHash: message.data.contentHash
          }
        }],
        riskScore: 0,
        riskLevel: 'low'
      }, {
        url: message.data.url
      }, {
        userFeedback: true,
        feedbackType: 'false-positive'
      }).catch(error => {
        console.error('Failed to send false positive report to telemetry:', error);
      });
    }

    return false;
  }

  // Frame context report from content script (evidence gathering)
  if (message.type === 'frame_context_report') {
    if (frameChainBuilder && sender.tab) {
      frameChainBuilder.mergeFrameContextReport(
        sender.tab.id, sender.frameId, message.data
      );
    }
    return false;
  }

  // Technology fingerprint report from content script
  if (message.type === 'tech_fingerprint_report') {
    if (frameChainBuilder && sender.tab) {
      frameChainBuilder.mergeTechFingerprint(
        sender.tab.id, sender.frameId, message.data
      );
    }
    // Fire-and-forget CVE lookup for main frame only
    if (cloudQueryClient && sender.tab && sender.frameId === 0) {
      cloudQueryClient.lookupVulnerabilities(message.data)
        .then(cveResult => {
          if (cveResult.summary?.total_cves > 0) {
            const state = tabDetections.get(sender.tab.id);
            if (state) state.vulnerabilities = cveResult;
          }
        })
        .catch(() => {}); // Non-blocking, best-effort
    }
    return false;
  }

  // Suspicious form/link (legacy)
  if (message.type === 'suspicious_form' || message.type === 'suspicious_link') {
    console.log('Suspicious content detected:', message.data);
    return false;
  }

  // Enhanced telemetry API
  if (message.type === 'getTelemetry') {
    const telemetry = {
      session: telemetryCollector.getSessionStats(),
      detectors: telemetryCollector.getTopDetectors(10),
      techniques: telemetryCollector.getTopTechniques(10),
      riskDistribution: telemetryCollector.getRiskDistribution(),
      actionDistribution: telemetryCollector.getActionDistribution()
    };
    sendResponse(telemetry);
    return true;
  }

  // Per-tab status API (for popup dual-shield display)
  // Reads from accumulated state — no new analysis triggered
  if (message.type === 'getTabStatus') {
    (async () => {
      try {
        // Determine tab ID
        let tabId = message.tabId;
        if (!tabId && sender.tab) tabId = sender.tab.id;
        if (!tabId) {
          const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true });
          tabId = activeTab?.id;
        }
        if (!tabId) {
          sendResponse({ error: 'no-tab', url: '', security: { overall: 'unknown' }, aiContent: { overall: 'unknown' } });
          return;
        }

        // Get tab URL from Chrome
        let tabUrl = '';
        try {
          const tab = await chrome.tabs.get(tabId);
          tabUrl = tab.url || tab.pendingUrl || '';
        } catch (e) {
          tabUrl = '';
        }

        const isHttps = tabUrl.startsWith('https://');
        const isHttp = tabUrl.startsWith('http://');
        const isWebPage = isHttps || isHttp;

        // --- Read from accumulated per-tab state ---
        const tabState = tabDetections.get(tabId) || null;
        const riskScore = tabState?.riskScore || 0;
        const riskLevel = tabState?.riskLevel || 'none';
        const findings = tabState?.findings || [];
        const findingsCount = findings.length;
        const tabAction = tabState?.action || 'allow';

        // --- Connection Security (derived from URL protocol) ---
        let connection = { level: 'unknown', details: 'Not a web page' };
        if (isHttps) connection = { level: 'secure', details: 'HTTPS connection' };
        else if (isHttp) connection = { level: 'insecure', details: 'HTTP \u2014 not encrypted' };

        // --- Domain Reputation (derived from FeatureStore signals) ---
        let reputation = { level: 'unknown', details: isWebPage ? 'No reputation data' : 'N/A' };
        if (featureStore && featureStore.hasTab(tabId)) {
          const snapshot = featureStore.getSnapshot(tabId);
          const repKeys = Object.entries(snapshot).filter(([k]) =>
            k.includes('reputation') || k.includes('domain') || k.includes('blacklist') || k.includes('blocklist')
          );
          if (repKeys.length > 0) {
            const hasMalicious = repKeys.some(([, f]) => f.value === true || f.value === 'malicious');
            const hasSuspicious = repKeys.some(([, f]) => f.value === 'suspicious');
            if (hasMalicious) reputation = { level: 'malicious', details: 'Domain flagged as malicious' };
            else if (hasSuspicious) reputation = { level: 'suspicious', details: 'Suspicious indicators found' };
            else reputation = { level: 'trusted', details: 'No negative signals' };
          }
        }

        // --- Server Fingerprint (tech stack + CVE enrichment) ---
        let fingerprint = { level: 'normal', details: 'Standard configuration' };
        if (isWebPage) {
          // Build tech stack summary + flat tech array from frame chain
          let techSummary = '';
          let techItems = []; // flat array of {name, version, category} for popup rendering
          try {
            const chain = frameChainBuilder ? frameChainBuilder.getChain(tabId, 0) : [];
            const techData = chain.length > 0 ? chain[0].technologies : null;
            if (techData) {
              const parts = [];
              // CMS: array of {name, version, ...}
              if (techData.cms && techData.cms.length > 0) {
                for (const c of techData.cms) {
                  techItems.push({ name: c.name, version: c.version || null, category: 'CMS' });
                }
                const c = techData.cms[0];
                parts.push(c.name + (c.version ? ' ' + c.version : ''));
              }
              // Client libraries: array of {name, version, ...}
              if (techData.clientLibs && techData.clientLibs.length > 0) {
                for (const lib of techData.clientLibs) {
                  techItems.push({ name: lib.name, version: lib.version || null, category: 'Library' });
                }
                const lib = techData.clientLibs[0];
                parts.push(lib.name + (lib.version ? ' ' + lib.version : ''));
                if (techData.clientLibs.length > 1) parts.push(`${techData.clientLibs.length - 1} more`);
              }
              // WordPress plugins
              if (techData.wpPlugins && techData.wpPlugins.length > 0) {
                for (const p of techData.wpPlugins) {
                  techItems.push({ name: p.name, version: p.version || null, category: 'Plugin' });
                }
                parts.push(`${techData.wpPlugins.length} plugin${techData.wpPlugins.length !== 1 ? 's' : ''}`);
              }
              // Frameworks
              if (techData.frameworks && techData.frameworks.length > 0) {
                for (const fw of techData.frameworks) {
                  techItems.push({ name: fw.name, version: fw.version || null, category: 'Framework' });
                }
                if (parts.length === 0) {
                  const fw = techData.frameworks[0];
                  parts.push(fw.name + (fw.version ? ' ' + fw.version : ''));
                }
              }
              techSummary = parts.join(' \u00b7 ');
            }
          } catch (e) { /* best effort */ }

          // Check CVE data cached in tabDetections
          const tabVulns = tabState?.vulnerabilities;
          // Tag each tech item with its worst CVE severity
          if (tabVulns?.vulnerabilities?.length > 0) {
            for (const item of techItems) {
              const matching = tabVulns.vulnerabilities.filter(v =>
                v.affected_technology?.name?.toLowerCase() === item.name.toLowerCase()
              );
              if (matching.length > 0) {
                const sevOrder = { critical: 4, high: 3, medium: 2, low: 1 };
                const worst = matching.reduce((w, v) => sevOrder[v.severity] > sevOrder[w.severity] ? v : w, matching[0]);
                item.cveCount = matching.length;
                item.worstSeverity = worst.severity;
              }
            }
          }

          const vulnPayload = tabVulns ? {
            summary: tabVulns.summary,
            vulns: (tabVulns.vulnerabilities || []).slice(0, 20)
          } : null;

          if (tabVulns?.summary?.critical > 0) {
            fingerprint = {
              level: 'vulnerable',
              details: techSummary || 'Vulnerable software detected',
              techStack: techSummary,
              technologies: techItems,
              vulnerabilities: vulnPayload
            };
          } else if (tabVulns?.summary?.high > 0) {
            fingerprint = {
              level: 'vulnerable',
              details: techSummary || 'High-severity CVEs detected',
              techStack: techSummary,
              technologies: techItems,
              vulnerabilities: vulnPayload
            };
          } else if (tabVulns?.summary?.medium > 0 || tabVulns?.summary?.low > 0) {
            fingerprint = {
              level: 'weak',
              details: techSummary || 'Minor vulnerabilities detected',
              techStack: techSummary,
              technologies: techItems,
              vulnerabilities: vulnPayload
            };
          } else if (techSummary) {
            fingerprint = { level: 'normal', details: techSummary, techStack: techSummary, technologies: techItems };
          }
        }

        // --- Content & Behavior (derived from accumulated detections + feature store) ---
        let behavior = { level: isWebPage ? 'clean' : 'unknown', details: isWebPage ? 'No issues detected' : 'N/A', monitoring: isWebPage };

        if (isWebPage) {
          // Check accumulated findings first — these are real detections
          if (findingsCount > 0) {
            const severityOrder = { critical: 4, high: 3, medium: 2, low: 1 };
            const maxSeverity = findings.reduce((max, f) => {
              return (severityOrder[f.severity] || 0) > (severityOrder[max] || 0) ? f.severity : max;
            }, 'low');

            if (maxSeverity === 'critical' || tabAction === 'block') {
              behavior = { level: 'dangerous', details: `${findingsCount} threat(s) \u2014 ${maxSeverity} severity`, monitoring: true };
            } else if (maxSeverity === 'high' || tabAction === 'warn') {
              behavior = { level: 'suspicious', details: `${findingsCount} threat(s) \u2014 ${maxSeverity} severity`, monitoring: true };
            } else {
              behavior = { level: 'suspicious', details: `${findingsCount} finding(s) detected`, monitoring: true };
            }
          } else {
            // No detections yet — check FeatureStore for behavioral signals
            if (featureStore && featureStore.hasTab(tabId)) {
              const snapshot = featureStore.getSnapshot(tabId);
              const behaviorKeys = Object.entries(snapshot).filter(([k]) =>
                k.includes('clipboard') || k.includes('injection') || k.includes('dialog') ||
                k.includes('command') || k.includes('social') || k.includes('credential') ||
                k.includes('suspicious') || k.includes('phish')
              );
              if (behaviorKeys.length > 0) {
                const hasPositive = behaviorKeys.some(([, f]) => f.value === true);
                if (hasPositive) {
                  behavior = { level: 'suspicious', details: `${behaviorKeys.length} behavioral signal(s)`, monitoring: true };
                }
                // If signals exist but all false, stay clean — they were checked and passed
              }
            }
          }
        }

        // --- Compute overall security level ---
        // Priority: detections/action > sub-indicator levels
        let securityOverall;
        if (tabAction === 'block' || riskLevel === 'critical' || riskLevel === 'high') {
          securityOverall = 'danger';
        } else if (tabAction === 'warn' || riskLevel === 'medium') {
          securityOverall = 'warning';
        } else {
          // Fall back to sub-indicator levels
          const levels = [connection.level, reputation.level, fingerprint.level, behavior.level];
          if (levels.includes('malicious') || levels.includes('dangerous') || levels.includes('insecure')) {
            securityOverall = 'danger';
          } else if (levels.includes('suspicious') || levels.includes('weak') || levels.includes('vulnerable')) {
            securityOverall = 'warning';
          } else if (isWebPage && levels.every(l => l !== 'unknown')) {
            securityOverall = 'safe';
          } else if (isWebPage) {
            securityOverall = 'safe'; // Default web page with no issues
          } else {
            securityOverall = 'unknown';
          }
        }

        sendResponse({
          url: tabUrl,
          security: {
            overall: securityOverall,
            connection,
            reputation,
            fingerprint,
            behavior
          },
          aiContent: (() => {
            const scans = tabContentScans.get(tabId);
            if (!scans || (scans.textScans.length === 0 && scans.imageScans.length === 0)) {
              return {
                overall: 'unknown',
                text: { level: 'unknown', count: 0 },
                images: { level: 'unknown', count: 0 },
                video: { level: 'unknown', count: 0 },
                authenticityScore: null
              };
            }

            // Text summary
            const textAI = scans.textScans.filter(s => s.verdict === 'ai_generated' || s.verdict === 'mixed' || s.verdict === 'likely_ai');
            const textUncertain = scans.textScans.filter(s => s.verdict === 'uncertain');
            const textLevel = scans.textScans.length === 0 ? 'unknown'
              : textAI.length > 0 ? 'danger'
              : textUncertain.length > 0 ? 'warning' : 'safe';

            // Verdict helpers — verdicts come from two paths:
            //   cloud:  ai_generated | manipulated | mixed | uncertain | human
            //   client: likely_ai | uncertain | likely_human
            // We normalize both so a "clean" image counts the same whether the
            // cloud was reachable or only the local heuristic ran.
            const isAi    = (v) => v === 'ai_generated' || v === 'manipulated' || v === 'mixed' || v === 'likely_ai';
            const isHuman = (v) => v === 'human' || v === 'likely_human';

            // Image summary
            const imageAI = scans.imageScans.filter(s => isAi(s.verdict));
            const imageUncertain = scans.imageScans.filter(s => s.verdict === 'uncertain');
            const imageLevel = scans.imageScans.length === 0 ? 'unknown'
              : imageAI.length > 0 ? 'danger'
              : imageUncertain.length > 0 ? 'warning' : 'safe';

            // Authenticity score:
            // human / likely_human → 100, uncertain → 50, ai-family → 0
            const allScans = [...scans.textScans, ...scans.imageScans];
            const scoreSum = allScans.reduce((sum, s) => {
              if (isHuman(s.verdict)) return sum + 100;
              if (s.verdict === 'uncertain') return sum + 50;
              return sum; // ai_generated, manipulated, mixed, likely_ai = 0
            }, 0);
            const authenticityScore = allScans.length > 0 ? Math.round(scoreSum / allScans.length) : null;

            // Overall: ignore 'unknown' categories (not scanned yet ≠ problem)
            const knownLevels = [textLevel, imageLevel].filter(l => l !== 'unknown');
            const overall = knownLevels.length === 0 ? 'unknown'
              : knownLevels.includes('danger') ? 'danger'
              : knownLevels.includes('warning') ? 'warning'
              : 'safe';

            return {
              overall,
              text: {
                level: textLevel,
                count: scans.textScans.length,
                aiCount: textAI.length,
                latestVerdict: scans.textScans.length > 0 ? scans.textScans[scans.textScans.length - 1].verdict : null,
                latestConfidence: scans.textScans.length > 0 ? scans.textScans[scans.textScans.length - 1].confidence : 0
              },
              images: {
                level: imageLevel,
                count: scans.imageScans.length,
                aiCount: imageAI.length,
                uncertainCount: imageUncertain.length,
                manipulated: scans.imageScans.filter(s => s.manipulationDetected).length,
                humanCount: scans.imageScans.filter(s => isHuman(s.verdict)).length,
                latestVerdict: scans.imageScans.length > 0 ? scans.imageScans[scans.imageScans.length - 1].verdict : null,
                latestConfidence: scans.imageScans.length > 0 ? scans.imageScans[scans.imageScans.length - 1].confidence : 0
              },
              video: { level: 'unknown', count: 0 },
              authenticityScore
            };
          })(),
          riskScore,
          riskLevel,
          findingsCount,
          findings: findings.slice(0, 10)
        });
      } catch (err) {
        console.error('getTabStatus error:', err);
        sendResponse({ error: err.message, url: '', security: { overall: 'unknown' }, aiContent: { overall: 'unknown' } });
      }
    })();
    return true;
  }

  // CVE status check (used by content.js form gate)
  if (message.type === 'getCveStatus') {
    const cveTabId = sender?.tab?.id;
    const tabVulns = cveTabId ? tabDetections.get(cveTabId)?.vulnerabilities : null;
    const summary = tabVulns?.summary;
    sendResponse({
      hasCriticalCves: (summary?.critical || 0) > 0 || (summary?.high || 0) > 0,
      totalCves: summary?.total_cves || 0,
      criticalCount: summary?.critical || 0,
      highCount: summary?.high || 0
    });
    return true;
  }

  // Policy management API
  if (message.type === 'getActivePolicy') {
    sendResponse({
      policyId: policyManager.getActivePolicyId(),
      policies: policyManager.getAllPolicies()
    });
    return true;
  }

  // Enterprise status API
  if (message.type === 'getEnterpriseStatus') {
    const status = {
      enterpriseMode: configManager.get('enterpriseMode'),
      mdm: mdmIntegration ? mdmIntegration.exportStatus() : null,
      adminConsole: adminConsole ? adminConsole.getConnectionStatus() : null,
      siem: siemReporter ? siemReporter.getStatistics() : null,
      clickhouse: clickhouseReporter ? clickhouseReporter.getStatistics() : null
    };
    sendResponse(status);
    return true;
  }

  // MDM configuration update
  if (message.type === 'mdm-config-update') {
    console.log('MDM configuration update:', message.category, message.data);

    // Handle configuration updates from MDM
    if (message.category === 'policy' && message.data.url) {
      policyManager.loadEnterprisePolicy().catch(error => {
        console.error('Failed to load MDM policy:', error);
      });
    }

    return false;
  }

  // Admin console configuration update
  if (message.type === 'admin-console-config-update') {
    console.log('Admin console configuration update:', message.category, message.data);
    return false;
  }

  // Get last detection (for blocked page)
  if (message.type === 'getLastDetection') {
    if (lastDetection) {
      sendResponse({
        findings: lastDetection.detection.findings,
        riskScore: lastDetection.detection.riskScore,
        riskLevel: lastDetection.detection.riskLevel,
        url: lastDetection.url,
        timestamp: lastDetection.timestamp
      });
    } else {
      sendResponse(null);
    }
    return true;
  }

  // Report false positive
  if (message.type === 'reportFalsePositive') {
    console.log('📢 False positive reported:', {
      url: message.url,
      riskScore: message.riskScore,
      timestamp: message.timestamp
    });

    // Log to audit
    if (auditLogger) {
      auditLogger.logUserAction('false-positive-report', {
        url: message.url,
        riskScore: message.riskScore,
        reportedAt: message.timestamp
      }).catch(error => {
        console.error('Failed to log false positive report:', error);
      });
    }

    // Report to admin console
    if (adminConsole && adminConsole.isConnected()) {
      adminConsole.reportFalsePositive({
        url: message.url,
        riskScore: message.riskScore,
        deviceId: configManager.get('deviceId'),
        organizationId: configManager.get('organizationId'),
        timestamp: message.timestamp
      }).catch(error => {
        console.error('Failed to report false positive to admin console:', error);
      });
    }

    sendResponse({ success: true });
    return true;
  }

  // HTTP upgraded to HTTPS
  if (message.type === 'httpUpgraded') {
    console.log('🔒 HTTP upgraded to HTTPS:', message.originalUrl, '->', message.httpsUrl);

    // Show success notification
    chrome.notifications.create({
      type: 'basic',
      iconUrl: 'icons/icon48.png',
      title: 'Connection Upgraded',
      message: 'Successfully upgraded to secure HTTPS connection',
      priority: 1
    });

    // Log to audit
    if (auditLogger) {
      auditLogger.logUserAction('http-upgraded', {
        originalUrl: message.originalUrl,
        httpsUrl: message.httpsUrl,
        timestamp: message.timestamp
      }).catch(error => {
        console.error('Failed to log HTTP upgrade:', error);
      });
    }

    sendResponse({ success: true });
    return true;
  }

  // Rule update status (for popup)
  if (message.type === 'getRuleUpdateStatus') {
    if (dynamicRuleUpdater) {
      sendResponse(dynamicRuleUpdater.getStatus());
    } else {
      sendResponse({ currentVersion: null, lastUpdateTime: null, isUpdating: false, stats: {} });
    }
    return true;
  }

  // Force rule update (from popup)
  if (message.type === 'forceRuleUpdate') {
    if (dynamicRuleUpdater) {
      dynamicRuleUpdater.forceUpdate().then(() => {
        sendResponse(dynamicRuleUpdater.getStatus());
      }).catch(error => {
        sendResponse({ error: error.message, ...dynamicRuleUpdater.getStatus() });
      });
    } else {
      sendResponse({ error: 'Dynamic rule updater not initialized' });
    }
    return true;
  }

  // Cloud telemetry settings updated
  if (message.type === 'cloudTelemetrySettingsUpdated') {
    const settings = message.settings;
    if (detectionReporter) {
      detectionReporter.updateConfig({
        enabled: settings.detectionReporting !== false,
        shareUrls: settings.shareUrls !== false,
        screenshotMode: settings.screenshotMode || 'full'
      });
    }
    if (cloudQueryClient) {
      cloudQueryClient.updateConfig({
        enabled: settings.cloudAnalysis || false,
        cloudUrl: settings.cloudAnalysisUrl || 'http://localhost:4011'
      });
    }
    sendResponse({ success: true });
    return true;
  }

  // Get cloud telemetry status
  if (message.type === 'getCloudTelemetryStatus') {
    sendResponse({
      detectionReporter: detectionReporter ? detectionReporter.getStatus() : null,
      cloudQueryClient: cloudQueryClient ? cloudQueryClient.getStatus() : null
    });
    return true;
  }

  // User allowed HTTP site
  if (message.type === 'allowHttp') {
    console.log('⚠️ User allowed HTTP site:', message.url);

    // Add to whitelist
    addToHttpWhitelist(message.url);

    // Log to audit
    if (auditLogger) {
      auditLogger.logUserAction('http-allowed', {
        url: message.url,
        timestamp: message.timestamp
      }).catch(error => {
        console.error('Failed to log HTTP allowance:', error);
      });
    }

    sendResponse({ success: true });
    return true;
  }

  return false;
});

// Web request listener for URL analysis (non-blocking, for telemetry only)
// Note: Actual blocking is done via declarativeNetRequest rules
// Not available in Firefox MV3 — guarded with feature check
if (chrome.webRequest?.onBeforeRequest) {
  chrome.webRequest.onBeforeRequest.addListener(
    analyzeUrlRequest,
    { urls: ["<all_urls>"] }
    // Removed "blocking" - not available in Manifest V3 without enterprise install
  );
}

// Permission monitoring
chrome.permissions.onAdded.addListener(handlePermissionAdd);

// v3: FeatureStore lifecycle — create/reset tab state on navigation, clean on tab close
chrome.webNavigation.onCommitted.addListener((details) => {
  if (details.frameId === 0) {
    // Main frame navigation — reset per-tab detection state
    tabDetections.delete(details.tabId);
    tabContentScans.delete(details.tabId);
    // Clear content detector cache so images get re-scanned on refresh
    if (contentDetector) contentDetector.clearCache();
    // Reset feature store
    if (featureStore) featureStore.createTab(details.tabId, details.url);
    // Update icon to reflect clean/unknown state for new page
    updateTabIcon(details.tabId, details.url);

    // AI Visibility: track if this is an AI domain
    if (aiVisibilityReporter) {
      try {
        const hostname = new URL(details.url).hostname;
        const aiMatch = matchAIDomain(hostname);
        if (aiMatch) {
          aiVisibilityReporter.trackTab(details.tabId, aiMatch.domain, aiMatch.service);
          // Record a login/visit event
          aiVisibilityReporter.record({
            eventType: 'login',
            domain: aiMatch.domain,
            service: aiMatch.service
          });
        } else {
          aiVisibilityReporter.untrackTab(details.tabId);
        }
      } catch (e) {
        // Invalid URL, ignore
      }
    }
  } else {
    // Sub-frame navigation — create frame entry
    if (featureStore) featureStore.createFrame(details.tabId, details.frameId);
  }
});

chrome.tabs.onRemoved.addListener((tabId) => {
  tabDetections.delete(tabId);
  tabContentScans.delete(tabId);
  if (featureStore) featureStore.removeTab(tabId);
  if (aiVisibilityReporter) aiVisibilityReporter.untrackTab(tabId);
});

// Update toolbar icon when user switches tabs
chrome.tabs.onActivated.addListener(({ tabId }) => {
  updateTabIcon(tabId);
});

// Update toolbar icon when a tab finishes loading (covers redirects, SPA navigations)
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  if (changeInfo.status === 'complete') {
    updateTabIcon(tabId, tab.url);
  }
});

// HTTP Site Whitelist - Sites user explicitly allowed to visit over HTTP
let httpWhitelist = new Set();

// Load HTTP whitelist from storage
chrome.storage.local.get(['httpWhitelist'], (result) => {
  if (result.httpWhitelist) {
    httpWhitelist = new Set(result.httpWhitelist);
    console.log('Loaded HTTP whitelist:', httpWhitelist.size, 'entries');
  }
});

// Save HTTP whitelist to storage
function saveHttpWhitelist() {
  chrome.storage.local.set({
    httpWhitelist: Array.from(httpWhitelist)
  }, () => {
    if (chrome.runtime.lastError) {
      console.error('Failed to save HTTP whitelist:', chrome.runtime.lastError);
    }
  });
}

// Check if URL is in HTTP whitelist
function isHttpWhitelisted(url) {
  try {
    const urlObj = new URL(url);
    const baseUrl = `${urlObj.protocol}//${urlObj.hostname}${urlObj.pathname}`;
    return httpWhitelist.has(baseUrl) || httpWhitelist.has(url);
  } catch (e) {
    return false;
  }
}

// Add URL to HTTP whitelist
function addToHttpWhitelist(url) {
  try {
    const urlObj = new URL(url);
    const baseUrl = `${urlObj.protocol}//${urlObj.hostname}${urlObj.pathname}`;
    httpWhitelist.add(baseUrl);
    saveHttpWhitelist();
    console.log('Added to HTTP whitelist:', baseUrl);
  } catch (e) {
    console.error('Failed to add to HTTP whitelist:', e);
  }
}

// OAuth/IdP redirect detection for identity tracking
const IDP_URL_PATTERNS = [
  /accounts\.google\.com/, /login\.microsoftonline\.com/, /.*\.okta\.com/,
  /login\.live\.com/, /github\.com\/login/, /auth0\.com/
];

chrome.webNavigation.onBeforeNavigate.addListener((details) => {
  if (details.frameId !== 0 || !identityManager) return;
  try {
    const url = new URL(details.url);
    const isIdP = IDP_URL_PATTERNS.some(p => p.test(url.hostname));
    if (isIdP) {
      // Track that this tab is going through an IdP flow
      console.log(`Identity: IdP redirect detected → ${url.hostname}`);
    }
  } catch (e) {
    // Invalid URL
  }
});

// HTTP navigation interception
chrome.webNavigation.onBeforeNavigate.addListener(
  async (details) => {
    // Only process main frame navigations
    if (details.frameId !== 0) return;

    const url = details.url;

    // Check if URL is HTTP (not HTTPS)
    if (!url.startsWith('http://')) return;

    // Skip localhost and loopback addresses
    if (url.match(/^http:\/\/(localhost|127\.0\.0\.1|::1|0\.0\.0\.0)/)) return;

    // Skip extension pages
    if (url.startsWith('chrome-extension://')) return;

    // Check if user has whitelisted this URL
    if (isHttpWhitelisted(url)) {
      console.log('HTTP site allowed (whitelisted):', url);
      return;
    }

    // Load settings to check if auto-upgrade is enabled
    const result = await chrome.storage.local.get(['settings']);
    const settings = result.settings || { autoUpgradeHttps: true };
    const autoUpgradeEnabled = settings.autoUpgradeHttps !== false; // Default to true

    console.log('HTTP detected:', url, '| Auto-upgrade:', autoUpgradeEnabled);

    // If auto-upgrade is enabled, try HTTPS first
    if (autoUpgradeEnabled) {
      const httpsUrl = url.replace(/^http:\/\//, 'https://');

      try {
        // Test if HTTPS is available
        const httpsAvailable = await testHttpsAvailability(httpsUrl);

        if (httpsAvailable) {
          // HTTPS works! Redirect directly
          console.log('✅ HTTPS available, upgrading automatically:', httpsUrl);

          // Increment HTTPS upgrades counter
          stats.httpsUpgrades++;
          saveLegacyStats();
          notifyStatsUpdate();

          // Show success notification
          chrome.notifications.create({
            type: 'basic',
            iconUrl: 'icons/icon48.png',
            title: 'Connection Upgraded to HTTPS',
            message: `Automatically upgraded to secure connection`,
            priority: 1
          });

          // Log to audit
          if (auditLogger) {
            auditLogger.logUserAction('http-auto-upgraded', {
              originalUrl: url,
              httpsUrl: httpsUrl,
              timestamp: Date.now()
            }).catch(error => {
              console.error('Failed to log HTTP auto-upgrade:', error);
            });
          }

          // Redirect to HTTPS
          chrome.tabs.update(details.tabId, {
            url: httpsUrl
          });

          return; // Exit early, upgrade successful
        }
      } catch (error) {
        console.log('❌ HTTPS not available, showing warning page:', error.message);
      }
    }

    // If we got here, either auto-upgrade is disabled or HTTPS failed
    // Show warning page
    const warningUrl = chrome.runtime.getURL('http-warning.html') +
                       '?url=' + encodeURIComponent(url) +
                       '&autoUpgrade=false';

    console.log('Showing HTTP warning page:', url);

    // Redirect to warning page
    chrome.tabs.update(details.tabId, {
      url: warningUrl
    });
  },
  { url: [{ schemes: ['http'] }] }
);

// Test if HTTPS is available for a URL
async function testHttpsAvailability(httpsUrl) {
  return new Promise((resolve) => {
    // Create a simple test using fetch with a timeout
    const controller = new AbortController();
    const timeoutId = setTimeout(() => {
      controller.abort();
      resolve(false);
    }, 3000); // 3 second timeout

    fetch(httpsUrl, {
      method: 'HEAD',
      mode: 'no-cors', // Don't care about CORS for this test
      signal: controller.signal,
      cache: 'no-cache'
    })
      .then(() => {
        clearTimeout(timeoutId);
        resolve(true); // HTTPS is available
      })
      .catch((error) => {
        clearTimeout(timeoutId);
        // If it's an abort error, HTTPS timed out
        if (error.name === 'AbortError') {
          resolve(false);
        } else {
          // Any other error means HTTPS isn't working
          resolve(false);
        }
      });
  });
}

// Download interception for HTTP sites
// chrome.downloads.onDeterminingFilename is not available in Firefox
if (chrome.downloads?.onDeterminingFilename) {
  chrome.downloads.onDeterminingFilename.addListener((downloadItem, suggest) => {
    // Check if download is from HTTP site
    if (downloadItem.url.startsWith('http://')) {
      // Show warning notification
      chrome.notifications.create({
        type: 'basic',
        iconUrl: 'icons/icon48.png',
        title: 'Insecure Download Warning',
        message: `Warning: Downloading from insecure HTTP site. File: ${downloadItem.filename}`,
        priority: 2
      });

      // Log the download
      console.log('HTTP download warning:', downloadItem.url);

      stats.suspiciousResources++;
      saveLegacyStats();
      notifyStatsUpdate();
    }

    // CVE-based download warning
    const dlTabId = downloadItem.tabId || -1;
    if (dlTabId > 0) {
      const tabVulns = tabDetections.get(dlTabId)?.vulnerabilities;
      if (tabVulns?.summary?.critical > 0 || tabVulns?.summary?.high > 0) {
        chrome.notifications.create({
          type: 'basic',
          iconUrl: 'icons/icon48.png',
          title: 'Download from Vulnerable Site',
          message: `This site has ${tabVulns.summary.total_cves} known CVE${tabVulns.summary.total_cves !== 1 ? 's' : ''} (${tabVulns.summary.critical} critical). File: ${downloadItem.filename}`,
          priority: 2
        });
        stats.suspiciousResources++;
        saveLegacyStats();
        notifyStatsUpdate();
      }
    }

    // Allow download to proceed
    suggest({ filename: downloadItem.filename });
  });
}

// Extension installation/update handler
chrome.runtime.onInstalled.addListener(async (details) => {
  console.log('PhishProtect installed/updated:', details.reason);

  // Initialize extension
  await initializeExtension();

  // Log installation event
  if (auditLogger) {
    await auditLogger.logPolicyChange('install', 'default', {
      source: 'extension',
      triggeredBy: details.reason
    });
  }
});

// Extension startup handler
chrome.runtime.onStartup.addListener(async () => {
  console.log('PhishProtect starting up...');
  await initializeExtension();
});

// Periodic tasks
setInterval(async () => {
  // Sync enterprise policy (if enabled)
  if (policyManager && configManager.get('enterpriseMode')) {
    await policyManager.syncEnterprisePolicy();
  }

  // Flush telemetry
  if (siemReporter) {
    await siemReporter.forceFlush();
  }

  if (clickhouseReporter) {
    await clickhouseReporter.forceFlush();
  }

  // Clean audit logs
  if (auditLogger) {
    await auditLogger.cleanOldLogs();
  }

}, 3600000); // Every hour

// Initialize on script load
initializeExtension().catch(error => {
  console.error('Failed to initialize on load:', error);
});

console.log('PhishProtect Enterprise background script loaded');
