/**
 * SecurityPanel — diagnostics data provider for token scope and rotation audits.
 *
 * Wraps an `ApiTokenAuditor` and exposes a snapshot of the current audit state
 * for the diagnostics view. Consumers subscribe to change notifications and
 * call `getSnapshot()` to retrieve a fresh rendering-ready view.
 *
 * This panel is push-passive: it does not drive timers. Callers trigger audits
 * by calling `runAudit()` — typically on a schedule or on relevant events.
 */
import { logger } from '../../../utils/logger.js';
import { DEFAULT_PANEL_CONFIG } from '../types.js';
// ---------------------------------------------------------------------------
// SecurityPanel
// ---------------------------------------------------------------------------
/**
 * SecurityPanel — diagnostics data provider for token scope and rotation audits.
 *
 * @remarks
 * Instantiated by the diagnostics bootstrap (deferred wiring pattern, same as
 * OpsPanel and ForensicsDataPanel). The panel is constructed once during
 * bootstrap and wired to the application-level `ApiTokenAuditor` instance;
 * individual callers do not construct it directly.
 *
 * Usage:
 * ```ts
 * const auditor = new ApiTokenAuditor({ managed: true });
 * const panel = new SecurityPanel(auditor);
 *
 * panel.subscribe(() => {
 *   const snap = panel.getSnapshot();
 *   render(snap);
 * });
 *
 * // Run audit (e.g. on schedule or event):
 * panel.runAudit();
 *
 * // On cleanup:
 * panel.dispose();
 * ```
 */
export class SecurityPanel {
    _auditor;
    _config;
    _subscribers = new Set();
    _lastReport = null;
    constructor(auditor, config = DEFAULT_PANEL_CONFIG) {
        this._auditor = auditor;
        this._config = config;
    }
    /**
     * Run a full audit of all registered tokens and notify subscribers.
     * Returns the report so callers can emit events or take action.
     */
    runAudit(now = Date.now()) {
        const report = this._auditor.auditAll(now);
        this._lastReport = report;
        this._notify();
        return report;
    }
    /**
     * getSnapshot — Returns the current security audit snapshot.
     * Returns an empty snapshot if no audit has been run yet.
     */
    getSnapshot() {
        const report = this._lastReport;
        if (!report) {
            return {
                managed: this._auditor.isManaged,
                totalTokens: this._auditor.tokenCount,
                results: [],
                blocked: [],
                scopeViolations: [],
                rotationWarnings: [],
                rotationOverdue: [],
                lastAuditAt: null,
                capturedAt: new Date().toISOString(),
            };
        }
        // Cap results for display using the panel's buffer limit
        const results = report.results.slice(0, this._config.bufferLimit);
        return {
            managed: this._auditor.isManaged,
            totalTokens: this._auditor.tokenCount,
            results,
            blocked: report.blocked,
            scopeViolations: report.scopeViolations,
            rotationWarnings: report.rotationWarnings,
            rotationOverdue: report.rotationOverdue,
            lastAuditAt: report.capturedAt,
            capturedAt: new Date().toISOString(),
        };
    }
    /**
     * Register a callback invoked whenever the panel state changes.
     * @returns An unsubscribe function.
     */
    subscribe(callback) {
        this._subscribers.add(callback);
        return () => this._subscribers.delete(callback);
    }
    /**
     * Release all subscriptions.
     */
    dispose() {
        this._subscribers.clear();
    }
    _notify() {
        for (const cb of this._subscribers) {
            try {
                cb();
            }
            catch (err) {
                logger.debug('[SecurityPanel] subscriber error', { err });
            }
        }
    }
}
