// PhishProtect Evidence: Response Header Capture
// Passively captures response headers for every frame navigation
// Used to identify server technologies, CDNs, and security headers

const HEADERS_OF_INTEREST = new Set([
  'server',
  'x-powered-by',
  'x-generator',
  'x-drupal-cache',
  'x-drupal-dynamic-cache',
  'x-magento-vary',
  'x-magento-cache-control',
  'x-magento-cache-debug',
  'via',
  'cf-ray',
  'cf-cache-status',
  'x-cache',
  'x-served-by',
  'x-frame-options',
  'content-security-policy',
  'x-content-type-options',
  'strict-transport-security',
  'x-xss-protection',
  'x-aspnet-version',
  'x-aspnetmvc-version',
  'x-shopify-stage',
  'x-wix-request-id',
  'x-squarespace-did',
  'x-vercel-id',
  'x-netlify-request-id',
  'x-amz-cf-id',
  'x-amz-request-id'
]);

// Cookie name patterns that reveal technologies
const COOKIE_SIGNATURES = [
  'PHPSESSID', 'JSESSIONID', 'ASP.NET_SessionId',
  'wp_', 'wordpress_', 'drupal', 'joomla',
  '_shopify', '__cfduid', 'AWSALB'
];

export class HeaderCapture {
  constructor() {
    // Map<tabId, Map<frameId, {url, headers, setCookieNames}>>
    this.store = new Map();
  }

  /**
   * Initialize the header capture listener
   */
  initialize() {
    // webRequest.onHeadersReceived is not available in Firefox MV3
    if (!chrome.webRequest?.onHeadersReceived) {
      console.warn('[HeaderCapture] webRequest API not available — header capture disabled');
      return;
    }
    chrome.webRequest.onHeadersReceived.addListener(
      (details) => this._onHeadersReceived(details),
      { urls: ['<all_urls>'], types: ['main_frame', 'sub_frame'] },
      ['responseHeaders']
    );

    // Clean up on main frame navigation
    chrome.webNavigation.onCommitted.addListener((details) => {
      if (details.frameId === 0) {
        // Main frame navigation — clear all frame data for this tab
        this.store.delete(details.tabId);
      }
    });

    // Clean up on tab close
    chrome.tabs.onRemoved.addListener((tabId) => {
      this.store.delete(tabId);
    });

    console.log('HeaderCapture: initialized');
  }

  /**
   * Get captured headers for a specific frame
   */
  getFrameHeaders(tabId, frameId) {
    const tabStore = this.store.get(tabId);
    if (!tabStore) return null;
    return tabStore.get(frameId) || null;
  }

  /**
   * Get all captured headers for a tab
   */
  getTabHeaders(tabId) {
    return this.store.get(tabId) || new Map();
  }

  /**
   * Internal: process captured headers
   */
  _onHeadersReceived(details) {
    const { tabId, frameId, url, responseHeaders } = details;
    if (tabId < 0) return; // Skip non-tab requests

    if (!this.store.has(tabId)) {
      this.store.set(tabId, new Map());
    }

    const filtered = {};
    const setCookieNames = [];

    for (const header of responseHeaders) {
      const nameLower = header.name.toLowerCase();

      if (HEADERS_OF_INTEREST.has(nameLower)) {
        filtered[nameLower] = header.value;
      }

      // Extract cookie names from Set-Cookie headers
      if (nameLower === 'set-cookie' && header.value) {
        const cookieName = header.value.split('=')[0].trim();
        for (const sig of COOKIE_SIGNATURES) {
          if (cookieName.toUpperCase().includes(sig.toUpperCase())) {
            setCookieNames.push(cookieName);
            break;
          }
        }
      }
    }

    this.store.get(tabId).set(frameId, {
      url,
      headers: filtered,
      setCookieNames,
      capturedAt: Date.now()
    });
  }

  /**
   * Destroy and remove listeners
   */
  destroy() {
    this.store.clear();
  }
}
