import { PolicyRegistry } from './policy-registry.js';
import { DivergencePanel } from '../diagnostics/panels/divergence.js';
import { PolicyPanel as PolicyDiagnosticsPanel } from '../diagnostics/panels/policy.js';
import { lintPolicyConfig } from './lint.js';
const MAX_PERMISSION_AUDIT = 100;
export class PolicyRuntimeState {
    _registry;
    _dashboard = null;
    _divergencePanel = null;
    _recentPermissionAudit = [];
    _lastSimulationSummary = null;
    _lastPreflightReview = null;
    _subscribers = new Set();
    constructor(registry = new PolicyRegistry()) {
        this._registry = registry;
    }
    getRegistry() {
        return this._registry;
    }
    getDashboard() {
        return this._dashboard;
    }
    getDivergencePanel() {
        return this._divergencePanel;
    }
    setDashboard(dashboard) {
        this._divergencePanel?.dispose();
        this._dashboard = dashboard;
        this._divergencePanel = dashboard ? new DivergencePanel(dashboard) : null;
        this.notify();
    }
    recordTrendEntry() {
        this._divergencePanel?.recordTrendEntry();
        this.notify();
    }
    getSnapshot() {
        const current = this._registry.getCurrent();
        const candidate = this._registry.getCandidate();
        const lintFindings = [
            ...(current ? lintPolicyConfig({ mode: 'custom', rules: current.rules }) : []),
            ...(candidate ? lintPolicyConfig({ mode: 'custom', rules: candidate.rules }) : []),
        ];
        const panel = new PolicyDiagnosticsPanel(this._registry, this._divergencePanel, this._recentPermissionAudit, lintFindings, this._lastSimulationSummary, this._lastPreflightReview);
        return panel.getSnapshot();
    }
    recordSimulationSummary(summary) {
        this._lastSimulationSummary = summary;
        this.notify();
    }
    recordPreflightReview(review) {
        this._lastPreflightReview = review;
        this.notify();
    }
    recordPermissionRequest(params) {
        this._upsertPermissionAudit({
            callId: params.callId,
            tool: params.tool,
            category: params.category,
            riskLevel: params.analysis.riskLevel,
            classification: params.analysis.classification,
            summary: params.analysis.summary,
            reasons: params.analysis.reasons,
            target: params.analysis.target,
            host: params.analysis.host,
            requestedAt: Date.now(),
        });
        this.notify();
    }
    recordPermissionDecision(params) {
        this._upsertPermissionAudit({
            callId: params.callId,
            tool: params.tool,
            category: params.category,
            approved: params.result.approved,
            sourceLayer: params.result.sourceLayer,
            reasonCode: params.result.reasonCode,
            riskLevel: params.result.analysis.riskLevel,
            classification: params.result.analysis.classification,
            summary: params.result.analysis.summary,
            reasons: params.result.analysis.reasons,
            target: params.result.analysis.target,
            host: params.result.analysis.host,
            requestedAt: Date.now(),
            decidedAt: Date.now(),
            persisted: params.result.persisted,
        });
        this.notify();
    }
    subscribe(callback) {
        this._subscribers.add(callback);
        return () => {
            this._subscribers.delete(callback);
        };
    }
    notify() {
        for (const cb of this._subscribers) {
            try {
                cb();
            }
            catch {
                // Panel/runtime subscribers must not break policy state propagation.
            }
        }
    }
    _upsertPermissionAudit(entry) {
        const existingIndex = this._recentPermissionAudit.findIndex((candidate) => candidate.callId === entry.callId);
        if (existingIndex >= 0) {
            this._recentPermissionAudit[existingIndex] = {
                ...this._recentPermissionAudit[existingIndex],
                ...entry,
                requestedAt: this._recentPermissionAudit[existingIndex]?.requestedAt ?? entry.requestedAt,
            };
        }
        else {
            this._recentPermissionAudit.unshift(entry);
            if (this._recentPermissionAudit.length > MAX_PERMISSION_AUDIT) {
                this._recentPermissionAudit.length = MAX_PERMISSION_AUDIT;
            }
        }
    }
}
