"use strict";
/**
 * ComponentStatusRegistry Class
 *
 * This module contains the ComponentStatusRegistry class which provides
 * centralized management of component health status.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.ComponentStatusRegistry = void 0;
const ComponentStatus_ts_1 = require("./ComponentStatus.js");
const types_ts_1 = require("./types.js");
const crossThread_ts_1 = require("./crossThread.js");
const errors_ts_1 = require("./errors.js");
/**
 * Component Status Registry Class
 * Provides a centralized registry for managing component health status
 */
class ComponentStatusRegistry {
    statusMap = new Map();
    /**
     * Reset the component status registry, clearing all existing status data
     * This should be called when the component system starts up
     */
    reset() {
        this.statusMap = new Map();
    }
    /**
     * Register or update component health status
     * This function allows components to report their own health status
     */
    setStatus(componentName, status, message, error) {
        if (!componentName || typeof componentName !== 'string') {
            throw new errors_ts_1.ComponentStatusOperationError(String(componentName), 'setStatus', 'Component name must be a non-empty string');
        }
        if (!Object.values(types_ts_1.COMPONENT_STATUS_LEVELS).includes(status)) {
            throw new errors_ts_1.ComponentStatusOperationError(componentName, 'setStatus', `Invalid status level: ${status}. Must be one of: ${Object.values(types_ts_1.COMPONENT_STATUS_LEVELS).join(', ')}`);
        }
        this.statusMap.set(componentName, new ComponentStatus_ts_1.ComponentStatus(status, message, error));
    }
    /**
     * Get the current status of a component
     */
    getStatus(componentName) {
        return this.statusMap.get(componentName);
    }
    /**
     * Get all component statuses
     */
    getAllStatuses() {
        return this.statusMap;
    }
    /**
     * Report component as healthy
     */
    reportHealthy(componentName, message) {
        this.setStatus(componentName, types_ts_1.COMPONENT_STATUS_LEVELS.HEALTHY, message);
    }
    /**
     * Report component error
     */
    reportError(componentName, error, message) {
        this.setStatus(componentName, types_ts_1.COMPONENT_STATUS_LEVELS.ERROR, message, error);
    }
    /**
     * Report component warning
     */
    reportWarning(componentName, message) {
        this.setStatus(componentName, types_ts_1.COMPONENT_STATUS_LEVELS.WARNING, message);
    }
    /**
     * Component Lifecycle Management
     */
    /**
     * Initialize component as loading - call this when component loading begins
     */
    initializeLoading(componentName, message) {
        this.setStatus(componentName, types_ts_1.COMPONENT_STATUS_LEVELS.LOADING, message || 'Component is loading');
    }
    /**
     * Mark component as successfully loaded
     */
    markLoaded(componentName, message) {
        this.setStatus(componentName, types_ts_1.COMPONENT_STATUS_LEVELS.HEALTHY, message || 'Component loaded successfully');
    }
    /**
     * Mark component as failed to load
     */
    markFailed(componentName, error, message) {
        this.setStatus(componentName, types_ts_1.COMPONENT_STATUS_LEVELS.ERROR, message, error);
    }
    /**
     * Get all components with a specific status level
     */
    getComponentsByStatus(statusLevel) {
        const result = [];
        for (const [name, status] of this.statusMap) {
            if (status.status === statusLevel) {
                result.push({ name, status });
            }
        }
        return result;
    }
    /**
     * Get a summary of all component statuses
     */
    getStatusSummary() {
        const summary = {
            [types_ts_1.COMPONENT_STATUS_LEVELS.HEALTHY]: 0,
            [types_ts_1.COMPONENT_STATUS_LEVELS.ERROR]: 0,
            [types_ts_1.COMPONENT_STATUS_LEVELS.WARNING]: 0,
            [types_ts_1.COMPONENT_STATUS_LEVELS.LOADING]: 0,
            [types_ts_1.COMPONENT_STATUS_LEVELS.UNKNOWN]: 0,
        };
        for (const status of this.statusMap.values()) {
            summary[status.status]++;
        }
        return summary;
    }
    /**
     * Static method to get aggregated component statuses from all threads
     * Returns a Map with one entry per component showing overall status and thread distribution
     */
    static async getAggregatedFromAllThreads(registry) {
        const allStatuses = await crossThread_ts_1.crossThreadCollector.collect(registry);
        return crossThread_ts_1.StatusAggregator.aggregate(allStatuses);
    }
    /**
     * Get aggregated status for a specific component and all its sub-components
     * This method handles both exact matches and sub-component aggregation
     *
     * @param componentName - The component name to look up (e.g., "application-template", "http")
     * @param consolidatedStatuses - Pre-fetched consolidated statuses from all threads (optional, will fetch if not provided)
     * @returns Aggregated status information for the component
     */
    async getAggregatedStatusFor(componentName, consolidatedStatuses) {
        // Get consolidated statuses from all threads if not provided
        if (!consolidatedStatuses) {
            consolidatedStatuses = await ComponentStatusRegistry.getAggregatedFromAllThreads(this);
        }
        // Collect all statuses related to this component
        const allStatuses = [];
        const componentPrefix = componentName + '.';
        // Add exact match if exists
        const exactMatch = consolidatedStatuses.get(componentName);
        if (exactMatch) {
            allStatuses.push({ key: componentName, ...exactMatch });
        }
        // Add sub-component statuses
        for (const [statusKey, statusValue] of consolidatedStatuses) {
            if (statusKey.startsWith(componentPrefix)) {
                allStatuses.push({ key: statusKey, ...statusValue });
            }
        }
        if (allStatuses.length === 0) {
            // No status found at all
            return {
                status: types_ts_1.COMPONENT_STATUS_LEVELS.UNKNOWN,
                message: 'The component has not been loaded yet (may need a restart)',
                lastChecked: { workers: {} },
            };
        }
        // Aggregate all statuses
        const hasErrors = allStatuses.some((s) => s.status === types_ts_1.COMPONENT_STATUS_LEVELS.ERROR);
        const hasLoading = allStatuses.some((s) => s.status === types_ts_1.COMPONENT_STATUS_LEVELS.LOADING);
        const overallStatus = hasErrors
            ? types_ts_1.COMPONENT_STATUS_LEVELS.ERROR
            : hasLoading
                ? types_ts_1.COMPONENT_STATUS_LEVELS.LOADING
                : types_ts_1.COMPONENT_STATUS_LEVELS.HEALTHY;
        // Show details if anything is not healthy
        let overallMessage = 'All components loaded successfully';
        const details = {};
        if (hasErrors || hasLoading) {
            const problemStatuses = allStatuses.filter((s) => s.status === types_ts_1.COMPONENT_STATUS_LEVELS.ERROR || s.status === types_ts_1.COMPONENT_STATUS_LEVELS.LOADING);
            overallMessage = problemStatuses.map((s) => `${s.key}: ${s.latestMessage || s.status}`).join('; ');
            // Include details for debugging
            for (const status of allStatuses) {
                if (status.status !== types_ts_1.COMPONENT_STATUS_LEVELS.HEALTHY) {
                    details[status.key] = {
                        status: status.status,
                        message: status.latestMessage,
                    };
                }
            }
        }
        return {
            status: overallStatus,
            message: overallMessage,
            ...(Object.keys(details).length > 0 && { details }),
            lastChecked: allStatuses[0]?.lastChecked || { workers: {} },
        };
    }
}
exports.ComponentStatusRegistry = ComponentStatusRegistry;
//# sourceMappingURL=ComponentStatusRegistry.js.map