// Policy Manager - Manages multiple policies and policy selection
// Handles policy lifecycle, caching, and selection logic

import { PolicyEngine } from './policy-engine.js';

export class PolicyManager {
  constructor(config = {}) {
    this.engine = new PolicyEngine(config);
    this.config = config;
    this.activePolicyId = 'default';
    this.policyCache = new Map();
    this.policyMetadata = new Map();
    this.lastSyncTime = null;
  }

  /**
   * Initialize policy manager with default or enterprise policies
   */
  async initialize() {
    // Load default policy
    const defaultPolicy = this.engine.createDefaultPolicy();
    this.engine.loadPolicy('default', defaultPolicy);
    this.activePolicyId = 'default';

    // Check for enterprise/managed configuration
    if (this.config.enterpriseMode) {
      await this.loadEnterprisePolicy();
    }

    // Load user-customized policy if exists
    await this.loadUserPolicy();
  }

  /**
   * Load enterprise policy from management endpoint
   */
  async loadEnterprisePolicy() {
    try {
      const endpoint = this.config.policyEndpoint ||
                      this.config.enterprisePolicyUrl;

      if (!endpoint) {
        console.warn('Enterprise mode enabled but no policy endpoint configured');
        return false;
      }

      const success = await this.engine.loadPolicyFromEndpoint(endpoint, 'enterprise');

      if (success) {
        this.activePolicyId = 'enterprise';
        this.lastSyncTime = Date.now();

        this.policyMetadata.set('enterprise', {
          source: 'remote',
          endpoint,
          lastSync: this.lastSyncTime,
          autoUpdate: true
        });

        console.log('Enterprise policy loaded successfully');
        return true;
      }

      return false;
    } catch (error) {
      console.error('Failed to load enterprise policy:', error);
      return false;
    }
  }

  /**
   * Load user-customized policy from storage
   */
  async loadUserPolicy() {
    try {
      const result = await chrome.storage.sync.get(['userPolicy']);

      if (result.userPolicy) {
        this.engine.loadPolicy('user', result.userPolicy);

        this.policyMetadata.set('user', {
          source: 'local',
          lastModified: result.userPolicy.lastModified || Date.now(),
          customized: true
        });

        // User policy takes precedence over default but not enterprise
        if (this.activePolicyId === 'default') {
          this.activePolicyId = 'user';
        }

        console.log('User policy loaded successfully');
        return true;
      }

      return false;
    } catch (error) {
      console.error('Failed to load user policy:', error);
      return false;
    }
  }

  /**
   * Save user policy to storage
   * @param {object} policyData - Policy to save
   */
  async saveUserPolicy(policyData) {
    try {
      policyData.lastModified = Date.now();

      await chrome.storage.sync.set({
        userPolicy: policyData
      });

      this.engine.loadPolicy('user', policyData);

      this.policyMetadata.set('user', {
        source: 'local',
        lastModified: policyData.lastModified,
        customized: true
      });

      return true;
    } catch (error) {
      console.error('Failed to save user policy:', error);
      return false;
    }
  }

  /**
   * Evaluate detection using active policy
   * @param {object} detection - Detection result
   * @returns {object} - Policy decision
   */
  evaluateDetection(detection) {
    return this.engine.evaluateDetection(detection, this.activePolicyId);
  }

  /**
   * Evaluate detection with specific policy
   * @param {object} detection - Detection result
   * @param {string} policyId - Policy to use
   * @returns {object} - Policy decision
   */
  evaluateWithPolicy(detection, policyId) {
    return this.engine.evaluateDetection(detection, policyId);
  }

  /**
   * Set active policy
   * @param {string} policyId - Policy to activate
   */
  setActivePolicy(policyId) {
    if (this.engine.getLoadedPolicies().includes(policyId)) {
      this.activePolicyId = policyId;
      return true;
    }

    console.error(`Policy not found: ${policyId}`);
    return false;
  }

  /**
   * Get active policy ID
   * @returns {string} - Active policy ID
   */
  getActivePolicyId() {
    return this.activePolicyId;
  }

  /**
   * Get policy selection order (priority)
   * Enterprise > User > Default
   * @returns {array} - Ordered policy IDs
   */
  getPolicyPriority() {
    const priority = [];

    if (this.engine.getLoadedPolicies().includes('enterprise')) {
      priority.push('enterprise');
    }

    if (this.engine.getLoadedPolicies().includes('user')) {
      priority.push('user');
    }

    priority.push('default');

    return priority;
  }

  /**
   * Sync enterprise policy (periodic update)
   */
  async syncEnterprisePolicy() {
    if (!this.config.enterpriseMode) {
      return false;
    }

    const metadata = this.policyMetadata.get('enterprise');

    if (!metadata || !metadata.autoUpdate) {
      return false;
    }

    // Check if sync is needed (based on interval)
    const syncInterval = this.config.policySyncInterval || 3600000; // 1 hour default
    const timeSinceLastSync = Date.now() - (this.lastSyncTime || 0);

    if (timeSinceLastSync < syncInterval) {
      return false; // Too soon to sync
    }

    return await this.loadEnterprisePolicy();
  }

  /**
   * Get policy metadata
   * @param {string} policyId - Policy ID
   * @returns {object} - Policy metadata
   */
  getPolicyMetadata(policyId) {
    return this.policyMetadata.get(policyId);
  }

  /**
   * Get all loaded policies with metadata
   * @returns {array} - Array of policies with metadata
   */
  getAllPolicies() {
    const policies = [];

    for (const policyId of this.engine.getLoadedPolicies()) {
      policies.push({
        id: policyId,
        metadata: this.policyMetadata.get(policyId) || {},
        isActive: policyId === this.activePolicyId,
        policy: this.engine.exportPolicy(policyId)
      });
    }

    return policies;
  }

  /**
   * Reset to default policy
   */
  resetToDefault() {
    this.activePolicyId = 'default';
    this.engine.removePolicy('user');
    this.policyMetadata.delete('user');

    chrome.storage.sync.remove('userPolicy');
  }

  /**
   * Create policy from template
   * @param {string} template - Template type (strict, balanced, permissive)
   * @returns {object} - Policy data
   */
  createPolicyFromTemplate(template) {
    switch (template) {
      case 'strict':
        return {
          version: '1.0.0',
          name: 'Strict Security Policy',
          description: 'Maximum protection with aggressive blocking',
          riskThresholds: {
            critical: 10,  // Lower threshold = more blocking
            high: 7,
            medium: 4,
            low: 0
          },
          rules: [
            {
              name: 'Block All High+ Threats',
              severity: 'high',
              action: 'block',
              description: 'Block high and critical threats'
            },
            {
              name: 'Quarantine Medium Threats',
              severity: 'medium',
              action: 'quarantine',
              description: 'Quarantine medium severity threats'
            },
            {
              name: 'Report Low Threats',
              severity: 'low',
              action: 'report',
              description: 'Report low severity threats'
            }
          ],
          defaultRule: {
            action: 'warn',
            description: 'Warn on unknown threats'
          }
        };

      case 'balanced':
        return this.engine.createDefaultPolicy();

      case 'permissive':
        return {
          version: '1.0.0',
          name: 'Permissive Policy',
          description: 'Minimal blocking, primarily reporting',
          riskThresholds: {
            critical: 20,  // Higher threshold = less blocking
            high: 15,
            medium: 10,
            low: 0
          },
          rules: [
            {
              name: 'Block Only Critical',
              severity: 'critical',
              action: 'warn',
              description: 'Warn on critical threats'
            },
            {
              name: 'Report All Others',
              action: 'report',
              description: 'Report all other threats'
            }
          ],
          defaultRule: {
            action: 'allow',
            description: 'Allow by default'
          }
        };

      default:
        return this.engine.createDefaultPolicy();
    }
  }

  /**
   * Validate custom policy before loading
   * @param {object} policyData - Policy to validate
   * @returns {object} - Validation result
   */
  validatePolicy(policyData) {
    try {
      this.engine.validatePolicy(policyData);
      return {
        valid: true,
        errors: []
      };
    } catch (error) {
      return {
        valid: false,
        errors: [error.message]
      };
    }
  }

  /**
   * Get policy statistics
   * @returns {object} - Policy stats
   */
  getStatistics() {
    return {
      totalPolicies: this.engine.getLoadedPolicies().length,
      activePolicy: this.activePolicyId,
      lastSync: this.lastSyncTime,
      enterpriseEnabled: this.config.enterpriseMode || false,
      policies: this.getAllPolicies().map(p => ({
        id: p.id,
        isActive: p.isActive,
        source: p.metadata.source || 'built-in'
      }))
    };
  }
}
