// Overbroad Permissions Detector - Detects extensions with excessive permissions
// Browser Techniques Line 186: Overbroad host permissions
// All-sites permissions amplify impact of compromise

import { BaseDetector } from '../base-detector.js';

export class OverbroadPermissionsDetector extends BaseDetector {
  constructor(config = {}) {
    super({
      name: 'overbroad-permissions',
      category: 'malicious-extensions',
      version: '1.0.0',
      description: 'Detects extensions with overbroad host permissions',
      weight: 2,
      severity: 'medium',
      ...config
    });
  }

  async detect(target, ruleRegistry) {
    const findings = [];

    // This detector requires extension manifest data
    const permissions = target.permissions || [];
    const hostPermissions = target.hostPermissions || [];
    const extensionId = target.extensionId;
    const extensionName = target.extensionName;
    const description = target.description || '';
    const category = target.category;

    if (permissions.length === 0 && hostPermissions.length === 0) {
      return this.createResult(false, [], 0);
    }

    const rules = ruleRegistry.getRules('malicious-extensions', 'overbroad-permissions');

    if (!rules) {
      return this.createResult(false, [], 0);
    }

    const allPermissions = [...permissions, ...hostPermissions];

    // 1. Detect <all_urls> permission
    if (allPermissions.includes('<all_urls>')) {
      const isJustified = this.isAllUrlsJustified(description, category, rules);

      if (!isJustified) {
        findings.push(this.createFinding({
          pattern: 'all-urls-permission',
          matched: '<all_urls>',
          description: 'Extension has access to all websites (potentially unnecessary)',
          severity: 'high',
          weight: 4,
          metadata: {
            extensionId,
            extensionName,
            category,
            technique: 'excessive-scope'
          }
        }));
      }
    }

    // 2. Detect broad wildcard patterns
    const broadWildcards = this.detectBroadWildcards(allPermissions);
    if (broadWildcards.length > 0) {
      findings.push(this.createFinding({
        pattern: 'broad-wildcard-permissions',
        matched: broadWildcards.join(', '),
        description: 'Extension uses broad wildcard host permissions',
        severity: 'medium',
        weight: 3,
        metadata: {
          extensionId,
          extensionName,
          wildcards: broadWildcards,
          technique: 'wildcard-abuse'
        }
      }));
    }

    // 3. Detect unnecessary sensitive permissions
    const unnecessaryPerms = this.detectUnnecessaryPermissions(
      permissions,
      description,
      category,
      rules
    );

    if (unnecessaryPerms.length > 0) {
      findings.push(this.createFinding({
        pattern: 'unnecessary-sensitive-permissions',
        matched: unnecessaryPerms.join(', '),
        description: 'Extension requests sensitive permissions that seem unnecessary',
        severity: 'medium',
        weight: 3,
        metadata: {
          extensionId,
          extensionName,
          unnecessaryPermissions: unnecessaryPerms,
          technique: 'permission-overreach'
        }
      }));
    }

    // 4. Detect permission count excess
    const permCount = allPermissions.length;
    if (permCount > (rules.excessivePermissionCount || 10)) {
      findings.push(this.createFinding({
        pattern: 'excessive-permission-count',
        matched: `${permCount} permissions`,
        description: `Extension requests ${permCount} permissions (potentially excessive)`,
        severity: 'low',
        weight: 1,
        metadata: {
          extensionId,
          extensionName,
          permissionCount: permCount,
          technique: 'permission-bloat'
        }
      }));
    }

    // 5. Detect risky permission combinations
    const riskyCombos = this.detectRiskyCombinations(permissions, rules);
    if (riskyCombos.length > 0) {
      for (const combo of riskyCombos) {
        findings.push(this.createFinding({
          pattern: 'risky-permission-combo',
          matched: combo.permissions.join(' + '),
          description: combo.description,
          severity: 'high',
          weight: 4,
          metadata: {
            extensionId,
            extensionName,
            permissions: combo.permissions,
            technique: 'permission-combination'
          }
        }));
      }
    }

    // 6. Detect mismatch between category and permissions
    if (category) {
      const mismatch = this.detectCategoryMismatch(category, permissions, rules);
      if (mismatch) {
        findings.push(this.createFinding({
          pattern: 'category-permission-mismatch',
          matched: `${category} with suspicious permissions`,
          description: `Extension category doesn't justify requested permissions`,
          severity: 'medium',
          weight: 2,
          metadata: {
            extensionId,
            extensionName,
            category,
            technique: 'permission-deception'
          }
        }));
      }
    }

    const matched = findings.length > 0;
    const riskScore = findings.reduce((sum, f) => sum + (f.weight || 1), 0);

    return this.createResult(matched, findings, riskScore);
  }

  isAllUrlsJustified(description, category, rules) {
    const justifiedCategories = rules.allUrlsJustifiedCategories || [
      'developer tools',
      'productivity',
      'accessibility',
      'web development'
    ];

    const justifiedKeywords = rules.allUrlsJustifiedKeywords || [
      'ad blocker',
      'adblocker',
      'privacy',
      'security',
      'developer',
      'inspector',
      'debugger',
      'screen reader',
      'translator',
      'password manager'
    ];

    // Check category
    if (category && justifiedCategories.includes(category.toLowerCase())) {
      return true;
    }

    // Check description keywords
    const descLower = description.toLowerCase();
    return justifiedKeywords.some(keyword => descLower.includes(keyword));
  }

  detectBroadWildcards(permissions) {
    const broadPatterns = [
      '*://*/*',
      'http://*/*',
      'https://*/*',
      '*://*/',
      '*://*.com/*',
      '*://*.org/*'
    ];

    return permissions.filter(perm => broadPatterns.includes(perm));
  }

  detectUnnecessaryPermissions(permissions, description, category, rules) {
    const sensitivePerms = rules.sensitivePermissions || [
      'clipboardRead',
      'clipboardWrite',
      'geolocation',
      'desktopCapture',
      'tabCapture',
      'debugger',
      'management',
      'nativeMessaging'
    ];

    const descLower = description.toLowerCase();
    const unnecessary = [];

    for (const perm of permissions) {
      if (sensitivePerms.includes(perm)) {
        // Check if permission is mentioned in description
        if (!descLower.includes(perm.toLowerCase())) {
          unnecessary.push(perm);
        }
      }
    }

    return unnecessary;
  }

  detectRiskyCombinations(permissions, rules) {
    const riskyCombos = rules.riskyCombinations || [
      {
        permissions: ['webRequest', 'webRequestBlocking'],
        description: 'Can intercept and modify web requests'
      },
      {
        permissions: ['cookies', 'webRequest'],
        description: 'Can steal cookies via request interception'
      },
      {
        permissions: ['tabs', 'webNavigation'],
        description: 'Full browsing activity tracking capability'
      }
    ];

    const detected = [];

    for (const combo of riskyCombos) {
      const hasAll = combo.permissions.every(perm => permissions.includes(perm));
      if (hasAll) {
        detected.push(combo);
      }
    }

    return detected;
  }

  detectCategoryMismatch(category, permissions, rules) {
    // Simple extensions shouldn't need powerful permissions
    const simpleCategories = rules.simpleCategories || [
      'fun',
      'shopping',
      'news',
      'blogging',
      'social'
    ];

    const powerfulPerms = [
      'webRequest',
      'webRequestBlocking',
      'debugger',
      'management',
      'proxy',
      '<all_urls>'
    ];

    if (simpleCategories.includes(category?.toLowerCase())) {
      return permissions.some(perm => powerfulPerms.includes(perm));
    }

    return false;
  }
}
