// engine/compliance/auto-remediator.ts — Auto-remediation for compliance gaps (SPEC-408)
import { mkdir, writeFile, access } from 'node:fs/promises';
import { join } from 'node:path';
import { specStore } from '../../storage/index.js';
import { analyzeComplianceGaps } from './gap-analyzer.js';
const FRAMEWORK_MAP = {
    SOC2: 'soc2-type2',
    GDPR: 'gdpr',
    HIPAA: 'hipaa',
    ISO27001: 'iso27001',
};
// ---------------------------------------------------------------------------
// Spec file writer
// ---------------------------------------------------------------------------
async function specDirExists(specDir) {
    try {
        await access(specDir);
        return true;
    }
    catch {
        return false;
    }
}
async function writeStubSpec(projectPath, specId, title, framework, criteria, dryRun) {
    if (dryRun) {
        return;
    }
    const specDir = join(projectPath, 'planu', 'specs', specId);
    await mkdir(specDir, { recursive: true });
    const criteriaLines = criteria.map((c) => `- [ ] ${c}`).join('\n');
    const now = new Date().toISOString();
    const specContent = [
        '---',
        `id: ${specId}`,
        `title: "${title}"`,
        `status: draft`,
        `tags: [compliance, ${framework.toLowerCase()}, auto-generated]`,
        `createdAt: ${now}`,
        '---',
        '',
        `# ${title}`,
        '',
        `Auto-generated compliance spec for ${framework} framework.`,
        '',
        '## Acceptance Criteria',
        '',
        criteriaLines,
        '',
    ].join('\n');
    await writeFile(join(specDir, 'spec.md'), specContent, 'utf-8');
}
// ---------------------------------------------------------------------------
// Manual action builders
// ---------------------------------------------------------------------------
function buildManualAction(controlId, controlName, criteria) {
    return {
        control: controlId,
        description: `${controlName} requires manual process implementation`,
        steps: [
            `Review control ${controlId}: ${controlName}`,
            'Identify existing policies and procedures that address this control',
            'Document evidence in a spec or decision record',
            ...criteria.map((c) => `Verify: ${c}`),
        ],
    };
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
 * For each compliance gap, creates a stub spec so the team has a tracked
 * work item. When dryRun=true, returns findings without writing any files.
 */
export async function autoRemediateCompliance(projectPath, projectId, framework, dryRun = false) {
    const catalogFramework = FRAMEWORK_MAP[framework];
    const specs = await specStore.listSpecs(projectId);
    const specInputs = specs.map((s) => ({
        id: s.id,
        title: s.title,
        description: '',
        status: s.status,
    }));
    const gapResult = analyzeComplianceGaps(catalogFramework, specInputs);
    const createdSpecs = [];
    const alreadyCovered = [];
    const manualActionRequired = [];
    const timestamp = Date.now();
    for (const control of gapResult.coverage) {
        if (control.status === 'passing') {
            alreadyCovered.push(control.controlId);
            continue;
        }
        if (control.status === 'missing') {
            const slugControl = control.controlId.toLowerCase().replace(/[^a-z0-9]/g, '-');
            const specId = `SPEC-auto-${slugControl}-${timestamp}`;
            const title = `${framework} ${control.controlId} — ${control.controlName}`;
            const specDir = join(projectPath, 'planu', 'specs', specId);
            if (await specDirExists(specDir)) {
                alreadyCovered.push(control.controlId);
                continue;
            }
            await writeStubSpec(projectPath, specId, title, framework, control.requiredCriteria, dryRun);
            createdSpecs.push(specId);
        }
        else {
            // partial — manual action to complete coverage
            manualActionRequired.push(buildManualAction(control.controlId, control.controlName, control.requiredCriteria));
        }
    }
    return {
        framework,
        createdSpecs,
        alreadyCovered,
        manualActionRequired,
    };
}
//# sourceMappingURL=auto-remediator.js.map