import { DEFAULT_COMPONENT_CONFIG, appendBounded } from '../types.js';
import { logger } from '../../../utils/logger.js';
import { summarizeError } from '../../../utils/error-display.js';
/**
 * ToolContractsPanel — diagnostics data provider for tool contract verification.
 *
 * Usage:
 * ```ts
 * const panel = new ToolContractsPanel();
 * panel.load(verifier.verifyAll(registry.list()));
 *
 * const entry = panel.get('exec');
 * const all = panel.getAll();
 * const failures = panel.getFailures();
 * ```
 */
export class ToolContractsPanel {
    _config;
    /** All contract entries keyed by tool name. */
    _entries = new Map();
    /** Subscribers to data changes. */
    _subscribers = new Set();
    /**
     * Bounded history of entries from previous load() calls, for audit.
     */
    _history = [];
    constructor(config = DEFAULT_COMPONENT_CONFIG) {
        this._config = config;
    }
    /**
     * Load (or reload) all verification results.
     * Replaces all current entries with the provided map.
     *
     * @param results - Map of tool name → ContractVerificationResult from ToolContractVerifier.
     */
    load(results) {
        this._entries.clear();
        for (const [name, result] of results) {
            const entry = this._toEntry(result);
            this._entries.set(name, entry);
            appendBounded(this._history, entry, this._config.bufferLimit);
        }
        this._notify();
    }
    /**
     * Upsert a single verification result.
     * Call this when a single tool is re-verified (e.g. after hot-reload).
     *
     * @param result - The updated ContractVerificationResult.
     */
    upsert(result) {
        const entry = this._toEntry(result);
        this._entries.set(result.toolName, entry);
        appendBounded(this._history, entry, this._config.bufferLimit);
        this._notify();
    }
    /**
     * Get the contract entry for a specific tool.
     *
     * @param toolName - The tool name to look up.
     * @returns The entry or undefined if not yet verified.
     */
    get(toolName) {
        return this._entries.get(toolName);
    }
    /**
     * Get all contract entries, sorted by tool name.
     */
    getAll() {
        return [...this._entries.values()].sort((a, b) => a.toolName.localeCompare(b.toolName));
    }
    /**
     * Get only tools that failed their contract checks (have error-level violations).
     */
    getFailures() {
        return this.getAll().filter((e) => !e.passed);
    }
    /**
     * Get only tools that passed with warnings.
     */
    getWarnings() {
        return this.getAll().filter((e) => e.passed && e.violations.some((v) => v.severity === 'warn'));
    }
    /**
     * Get only tools that passed all checks cleanly.
     */
    getClean() {
        return this.getAll().filter((e) => e.passed && e.violations.every((v) => v.severity !== 'warn'));
    }
    /**
     * Summary counts across all entries.
     */
    getSummary() {
        let passed = 0;
        let passedWithWarnings = 0;
        let failed = 0;
        let totalViolations = 0;
        let totalErrors = 0;
        let totalWarnings = 0;
        for (const e of this._entries.values()) {
            let errors = 0;
            let warns = 0;
            for (const v of e.violations) {
                if (v.severity === 'error')
                    errors++;
                else
                    warns++;
            }
            totalViolations += e.violations.length;
            totalErrors += errors;
            totalWarnings += warns;
            if (e.passed) {
                if (warns > 0)
                    passedWithWarnings++;
                else
                    passed++;
            }
            else {
                failed++;
            }
        }
        return {
            total: this._entries.size,
            passed,
            passedWithWarnings,
            failed,
            totalViolations,
            totalErrors,
            totalWarnings,
        };
    }
    /**
     * Register a callback invoked whenever the data changes.
     * @returns An unsubscribe function.
     */
    subscribe(callback) {
        this._subscribers.add(callback);
        return () => this._subscribers.delete(callback);
    }
    /**
     * Release all subscriptions and clear internal state.
     */
    dispose() {
        this._subscribers.clear();
        this._entries.clear();
        this._history.length = 0;
    }
    _toEntry(result) {
        return {
            toolName: result.toolName,
            passed: result.passed,
            violations: result.violations.map((v) => ({
                dimension: v.dimension,
                severity: v.severity,
                message: v.message,
                hint: v.hint,
            })),
            verifiedAt: result.verifiedAt,
            isPhasedTool: result.isPhasedTool,
        };
    }
    _notify() {
        for (const cb of this._subscribers) {
            try {
                cb();
            }
            catch (err) {
                logger.warn('[ToolContractsPanel] subscriber error', { error: summarizeError(err) });
            }
        }
    }
}
