// Copyright (c) 2026 defconxt. All rights reserved.
// Licensed under AGPL-3.0 — see LICENSE file for details.

import { BaseHandler } from './base.js';

/**
 * PRIVACY mode handler — privacy engineering & compliance.
 * Adds: dpia, data-flow, regulations
 */
export class PrivacyHandler extends BaseHandler {
  constructor() { super('privacy'); }

  domainActions() {
    return ['dpia', 'data-flow', 'regulations'];
  }

  describeDomain(action) {
    return {
      'dpia':        'Generate Data Protection Impact Assessment structure',
      'data-flow':   'Extract data flow mappings and processing activities',
      'regulations': 'Map applicable regulations and compliance requirements',
    }[action];
  }

  async executeDomain(command, ctx) {
    switch (command) {
      case 'dpia':        return this.dpia(ctx);
      case 'data-flow':   return this.dataFlow(ctx);
      case 'regulations': return this.regulations(ctx);
      default: throw new Error(`Unknown PRIVACY command: ${command}`);
    }
  }

  /** Generate DPIA structure. */
  dpia(ctx) {
    const { skill, technique } = ctx;
    if (!skill) throw new Error('No SKILL.md found');

    const scope = ctx.flags.scope || 'unspecified';

    // Extract risk items from tables
    const risks = [];
    for (const table of skill.tables) {
      if (table.headers.some(h => /risk|threat|impact|severity|likelihood/i.test(h))) {
        for (const row of table.rows) {
          risks.push(row);
        }
      }
    }

    // Extract checklist items
    const checks = [];
    const checkRe = /^\s*[-*] \[([x ])\] (.+)$/gm;
    let m;
    while ((m = checkRe.exec(skill.raw))) {
      checks.push({ item: m[2].trim(), checked: m[1] === 'x' });
    }

    // Extract mitigation sections
    const mitigations = skill.sections
      .filter(s => /mitigat|control|safeguard|measure|protect/i.test(s.title))
      .map(s => ({
        area: s.title,
        content: s.content.slice(0, 400),
      }));

    const regs = this.extractRegulations(skill);

    return {
      action: 'dpia',
      technique,
      mode: 'PRIVACY',
      scope,
      risks: risks.slice(0, 20),
      checks: checks.slice(0, 30),
      mitigations: mitigations.slice(0, 10),
      regulations: regs,
      regulationValidation: this.validateRegulations(regs),
      status: 'dpia_complete',
    };
  }

  /** Extract data flow mappings. */
  dataFlow(ctx) {
    const { skill, technique } = ctx;
    if (!skill) throw new Error('No SKILL.md found');

    // Extract data flow sections
    const flows = skill.sections
      .filter(s => /data.flow|process|transfer|collect|stor|shar/i.test(s.title))
      .map(s => ({
        phase: s.title,
        content: s.content.slice(0, 400),
      }));

    // Extract from tables with data categories
    const dataCategories = [];
    for (const table of skill.tables) {
      if (table.headers.some(h => /data|category|type|field|pii|personal/i.test(h))) {
        for (const row of table.rows) {
          dataCategories.push(row);
        }
      }
    }

    // Extract diagrams (mermaid blocks)
    const diagrams = skill.codeBlocks
      .filter(b => b.lang === 'mermaid' || b.context.toLowerCase().includes('flow'))
      .map(b => ({ context: b.context, code: b.code }));

    return {
      action: 'data-flow',
      technique,
      mode: 'PRIVACY',
      flows: flows.slice(0, 10),
      dataCategories: dataCategories.slice(0, 20),
      diagrams: diagrams.slice(0, 5),
      status: 'data_flow_complete',
    };
  }

  /** Map applicable regulations. */
  regulations(ctx) {
    const { skill, technique } = ctx;
    if (!skill) throw new Error('No SKILL.md found');

    const regs = this.extractRegulations(skill);
    return {
      action: 'regulations',
      technique,
      mode: 'PRIVACY',
      regulations: regs,
      regulationValidation: this.validateRegulations(regs),
      status: 'regulations_complete',
    };
  }

  /** Validate regulatory references for correct format and article/section ranges. */
  validateRegulations(refs) {
    if (!Array.isArray(refs)) return { valid: [], invalid: [], unknown: [] };
    const valid = [];
    const invalid = [];
    const unknown = [];
    const knownFrameworks = /^(HIPAA|CCPA|PCI[\s-]DSS|SOX|SOC\s*[12]|FERPA|COPPA|LGPD|PIPEDA|NIST|ISO|OWASP|MITRE)/i;

    for (const ref of refs) {
      const s = String(ref).trim();
      // GDPR: validate article number 1-99
      const gdprMatch = s.match(/GDPR\s*Art(?:icle)?\.?\s*(\d+)/i);
      if (gdprMatch) {
        const num = parseInt(gdprMatch[1], 10);
        if (num >= 1 && num <= 99) { valid.push(s); } else { invalid.push(s); }
        continue;
      }
      if (/^GDPR$/i.test(s)) { valid.push(s); continue; }
      // Known frameworks accepted as valid
      if (knownFrameworks.test(s)) { valid.push(s); continue; }
      unknown.push(s);
    }
    return { valid, invalid, unknown };
  }

  /** Extract regulatory references from content. */
  extractRegulations(skill) {
    const regs = new Set();
    const patterns = [
      /GDPR\s*(?:Art(?:icle)?\.?\s*\d+(?:\(\d+\))?)/gi,
      /CCPA\s*(?:§?\s*\d+(?:\.\d+)?)?/gi,
      /HIPAA\s*(?:§?\s*\d+(?:\.\d+)?)?/gi,
      /PCI[\s-]DSS\s*(?:\d+(?:\.\d+)*)?/gi,
      /SOX\s*(?:§?\s*\d+)?/gi,
      /NIST\s*(?:SP\s*)?(?:800-\d+(?:[A-Z])?)?/gi,
      /ISO\s*(?:27\d{3}(?:[-:]\d+)?)/gi,
      /SOC\s*[12]/gi,
      /FERPA/gi,
      /COPPA/gi,
      /LGPD/gi,
      /PIPEDA/gi,
    ];

    for (const re of patterns) {
      let m;
      while ((m = re.exec(skill.raw))) {
        regs.add(m[0].trim());
      }
    }

    return [...regs];
  }
}
