/**
 * AuditScheduler -- Schedules and executes compliance audit runs.
 *
 * Manages recurring audit configurations, persists schedule to disk,
 * and orchestrates audit execution across compliance bots.
 *
 * GATE 11: Compliance Audit Bot System (T-153)
 *
 * @connexum/ai-governance
 */
import * as fs from 'fs';
import * as path from 'path';
import * as crypto from 'crypto';
export class AuditScheduler {
    logDir;
    packs;
    schedules = new Map();
    lastRuns = new Map();
    runners = new Map();
    scheduleFile;
    constructor(config) {
        this.logDir = config.logDir;
        this.packs = config.packs || [];
        this.scheduleFile = path.join(this.logDir, 'audit-schedule.json');
        if (!fs.existsSync(this.logDir)) {
            fs.mkdirSync(this.logDir, { recursive: true });
        }
        this.loadSchedule();
    }
    /**
     * Register an audit runner for a given pack ID.
     */
    registerRunner(packId, runner) {
        this.runners.set(packId, runner);
    }
    /**
     * Schedule a new audit. Returns the audit ID.
     */
    scheduleAudit(config) {
        const id = crypto.randomBytes(8).toString('hex');
        const scheduled = {
            id,
            config,
            createdAt: new Date().toISOString(),
            active: true,
        };
        this.schedules.set(id, scheduled);
        this.persistSchedule();
        return id;
    }
    /**
     * Execute a scheduled audit immediately. Returns the run result.
     */
    runAudit(auditId) {
        const scheduled = this.schedules.get(auditId);
        if (!scheduled) {
            throw new Error(`Audit ${auditId} not found`);
        }
        if (!scheduled.active) {
            throw new Error(`Audit ${auditId} is cancelled`);
        }
        const runner = this.runners.get(scheduled.config.packId);
        if (runner) {
            const result = runner.runAudit();
            result.auditId = auditId;
            this.lastRuns.set(auditId, result);
            return result;
        }
        // No runner registered -- return an empty result
        const result = {
            auditId,
            packId: scheduled.config.packId,
            timestamp: new Date().toISOString(),
            checks: [],
            score: 0,
            passed: 0,
            failed: 0,
            warnings: 0,
        };
        this.lastRuns.set(auditId, result);
        return result;
    }
    /**
     * List all scheduled audits.
     */
    getSchedule() {
        return Array.from(this.schedules.values());
    }
    /**
     * Cancel a scheduled audit.
     */
    cancelAudit(auditId) {
        const scheduled = this.schedules.get(auditId);
        if (!scheduled)
            return false;
        scheduled.active = false;
        this.persistSchedule();
        return true;
    }
    /**
     * Get the result of the most recent run for an audit.
     */
    getLastRun(auditId) {
        return this.lastRuns.get(auditId) || null;
    }
    // --- Persistence ---
    persistSchedule() {
        const data = Array.from(this.schedules.values());
        fs.writeFileSync(this.scheduleFile, JSON.stringify(data, null, 2));
    }
    loadSchedule() {
        if (!fs.existsSync(this.scheduleFile))
            return;
        try {
            const raw = fs.readFileSync(this.scheduleFile, 'utf-8');
            const data = JSON.parse(raw);
            for (const entry of data) {
                this.schedules.set(entry.id, entry);
            }
        }
        catch {
            // Corrupted schedule file -- start fresh
        }
    }
}
/**
 * Compute score and counts from an array of CheckResults.
 */
export function computeAuditScore(checks) {
    const passed = checks.filter((c) => c.status === 'pass').length;
    const failed = checks.filter((c) => c.status === 'fail').length;
    const warnings = checks.filter((c) => c.status === 'warning').length;
    const scorable = checks.filter((c) => c.status !== 'skip').length;
    const score = scorable > 0 ? Math.round((passed / scorable) * 100) : 0;
    return { score, passed, failed, warnings };
}
//# sourceMappingURL=scheduler.js.map