import { serializeSafe } from '../../inspection/state-inspector/serialize.js';
/**
 * StateInspectorPanel — on-demand runtime state snapshot provider.
 *
 * Domains are registered at construction time. Call `getSnapshot()` to
 * capture the current state of all registered domains.
 *
 * Optionally accepts a `HotspotReportProvider` callback to surface
 * selector hotspot analysis. Call `getHotspotAnalysis()` to retrieve
 * the current view.
 *
 * Unlike event-driven panels, this panel does not maintain an internal
 * buffer — each `getSnapshot()` call produces a fresh snapshot.
 */
export class StateInspectorPanel {
    _domains;
    /** Registered change notification callbacks. */
    _subscribers = new Set();
    /** Optional hotspot report provider. */
    _hotspotProvider;
    /**
     * @param domains - Array of domain adapters to inspect.
     * @param hotspotProvider - Optional provider for selector hotspot reports.
     */
    constructor(domains = [], hotspotProvider) {
        this._domains = domains;
        this._hotspotProvider = hotspotProvider;
    }
    /**
     * Register an additional domain for inspection after construction.
     *
     * @param domain - Domain adapter to add.
     */
    registerDomain(domain) {
        this._domains.push(domain);
        this._notify();
    }
    /**
     * Capture a point-in-time snapshot of all registered domains.
     * Maps and Sets in the state are converted to plain objects/arrays.
     *
     * @returns An immutable RuntimeStateSnapshot.
     */
    getSnapshot() {
        const entries = this._domains.map((domain) => ({
            domain: domain.name,
            revision: domain.getRevision(),
            lastUpdatedAt: domain.getLastUpdatedAt(),
            state: serializeSafe(domain.getState()),
        }));
        return {
            capturedAt: Date.now(),
            domains: entries,
        };
    }
    /**
     * Attach or replace the hotspot report provider.
     *
     * @param provider - Callback returning the current HotspotReport.
     */
    setHotspotProvider(provider) {
        this._hotspotProvider = provider;
    }
    /**
     * Return a structured hotspot analysis view for the diagnostics UI.
     *
     * Produces top-5 churn hotspots (by calls/sec) and top-5 latency
     * hotspots (by p95) from the current report. Returns an empty view
     * when no hotspot provider is attached.
     *
     * @returns HotspotAnalysisView.
     */
    getHotspotAnalysis() {
        const report = this._hotspotProvider?.();
        if (!report) {
            return {
                report: undefined,
                topChurn: [],
                topLatency: [],
                hasChurnHotspots: false,
                hasLatencyHotspots: false,
            };
        }
        const { hotspots } = report;
        // Top churn: highest callsPerSecond
        const topChurn = [...hotspots]
            .sort((a, b) => b.callsPerSecond - a.callsPerSecond)
            .slice(0, 5);
        // Top latency: highest p95
        const topLatency = [...hotspots]
            .sort((a, b) => b.p95Ms - a.p95Ms)
            .slice(0, 5);
        return {
            report,
            topChurn,
            topLatency,
            hasChurnHotspots: hotspots.some((h) => h.isChurnHotspot),
            hasLatencyHotspots: hotspots.some((h) => h.isLatencyHotspot),
        };
    }
    /**
     * Register a callback invoked when the domain registry changes.
     * Note: callbacks are NOT invoked on every state mutation — call
     * `getSnapshot()` on demand to retrieve current state.
     *
     * @returns An unsubscribe function.
     */
    subscribe(callback) {
        this._subscribers.add(callback);
        return () => this._subscribers.delete(callback);
    }
    _notify() {
        for (const cb of this._subscribers) {
            try {
                cb();
            }
            catch {
                // Non-fatal: subscriber errors must not crash the provider
            }
        }
    }
}
