/**
 * Risk Scan Scheduler
 *
 * Runs the SupplyRiskDetector on a configurable interval (default: 15 min).
 * Persists alerts, generates recommendations, and optionally auto-executes
 * critical actions when auto_action is enabled.
 */
import { SupplyRiskDetector } from './detector.js';
import { RiskRecommender } from './recommender.js';
// ============================================================================
// RiskScanScheduler
// ============================================================================
export class RiskScanScheduler {
    thresholds;
    adapter;
    timer = null;
    detector;
    recommender;
    lastScan = null;
    /** In-memory alert store (production would use DB). */
    alerts = new Map();
    /** In-memory recommendation store. */
    recommendations = new Map();
    constructor(thresholds, adapter, capacities = []) {
        this.thresholds = thresholds;
        this.adapter = adapter;
        this.detector = new SupplyRiskDetector(thresholds);
        this.recommender = new RiskRecommender(thresholds, capacities);
    }
    /** Start the periodic scan. Default interval: 15 minutes. */
    start(intervalMs = 15 * 60 * 1000) {
        if (this.timer)
            return;
        // Run immediately, then on interval
        void this.runScan();
        this.timer = setInterval(() => void this.runScan(), intervalMs);
    }
    stop() {
        if (this.timer) {
            clearInterval(this.timer);
            this.timer = null;
        }
    }
    get isRunning() {
        return this.timer !== null;
    }
    get lastScanResult() {
        return this.lastScan;
    }
    /** Trigger an immediate scan (also called by the POST /risk/scan endpoint). */
    async runScan() {
        const [inventory, demand, capacities] = await Promise.all([
            this.adapter.getInventorySnapshots(),
            this.adapter.getDemandSignals(),
            this.adapter.getFacilityCapacities(),
        ]);
        // Detect risks
        const risks = this.detector.detect(inventory, demand, capacities);
        // Generate recommendations
        const recs = this.recommender.generateRecommendations(risks);
        const now = new Date().toISOString();
        const scanId = `scan-${crypto.randomUUID().slice(0, 8)}`;
        const newAlerts = [];
        let autoExecuted = 0;
        // Persist alerts
        for (const risk of risks) {
            const alertId = `alert-${crypto.randomUUID().slice(0, 8)}`;
            const alert = {
                id: alertId,
                risk,
                status: 'open',
                created_at: now,
            };
            this.alerts.set(alertId, alert);
            newAlerts.push(alert);
            await this.adapter.persistAlert(alert);
        }
        // Store recommendations
        for (const rec of recs) {
            this.recommendations.set(rec.id, rec);
        }
        // Auto-execute critical recommendations if enabled
        if (this.thresholds.autoActionEnabled) {
            for (const rec of recs) {
                if (rec.urgency_score >= 90 &&
                    rec.estimated_cost <= this.thresholds.autoActionMaxValue) {
                    const result = await this.adapter.executeRecommendation(rec);
                    if (result.success) {
                        autoExecuted++;
                        this.recommendations.set(rec.id, { ...rec, status: 'executed' });
                    }
                }
            }
        }
        const scanResult = {
            scan_id: scanId,
            timestamp: now,
            risks_detected: risks.length,
            recommendations_generated: recs.length,
            auto_executed: autoExecuted,
            alerts: newAlerts,
            recommendations: recs,
        };
        this.lastScan = scanResult;
        return scanResult;
    }
    // ── Alert queries ──────────────────────────────────────────────────────
    getAlerts(filter) {
        let results = Array.from(this.alerts.values());
        if (filter?.status)
            results = results.filter((a) => a.status === filter.status);
        if (filter?.facility_id)
            results = results.filter((a) => a.risk.facility_id === filter.facility_id);
        if (filter?.sku)
            results = results.filter((a) => a.risk.sku === filter.sku);
        return results.sort((a, b) => b.created_at.localeCompare(a.created_at));
    }
    resolveAlert(alertId, resolvedBy, notes) {
        const alert = this.alerts.get(alertId);
        if (!alert || alert.status === 'resolved')
            return null;
        const resolved = {
            ...alert,
            status: 'resolved',
            resolved_at: new Date().toISOString(),
            resolved_by: resolvedBy,
            resolution_notes: notes,
        };
        this.alerts.set(alertId, resolved);
        return resolved;
    }
    // ── Recommendation queries ─────────────────────────────────────────────
    getRecommendations(filter) {
        let results = Array.from(this.recommendations.values());
        if (filter?.status)
            results = results.filter((r) => r.status === filter.status);
        return results.sort((a, b) => b.urgency_score - a.urgency_score);
    }
    async executeRecommendation(recId) {
        const rec = this.recommendations.get(recId);
        if (!rec || rec.status !== 'pending')
            return null;
        const result = await this.adapter.executeRecommendation(rec);
        if (result.success) {
            this.recommendations.set(recId, { ...rec, status: 'executed' });
        }
        return result;
    }
}
//# sourceMappingURL=scheduler.js.map