// SPDX-License-Identifier: Apache-2.0
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var RemoteConfigValidator_1;
import { inject, injectable } from 'tsyringe-neo';
import { patchInject } from '../../dependency-injection/container-helper.js';
import { InjectTokens } from '../../dependency-injection/inject-tokens.js';
import { SoloError } from '../../errors/solo-error.js';
import { Templates } from '../../templates.js';
import { DeploymentPhase } from '../../../data/schema/model/remote/deployment-phase.js';
import * as constants from '../../constants.js';
/**
 * Static class is used to validate that components in the remote config
 * are present in the kubernetes cluster, and throw errors if there is mismatch.
 */
let RemoteConfigValidator = class RemoteConfigValidator {
    static { RemoteConfigValidator_1 = this; }
    k8Factory;
    localConfig;
    chartManager;
    constructor(k8Factory, localConfig, chartManager) {
        this.k8Factory = k8Factory;
        this.localConfig = localConfig;
        this.chartManager = chartManager;
        this.k8Factory = patchInject(k8Factory, InjectTokens.K8Factory, this.constructor.name);
        this.localConfig = patchInject(localConfig, InjectTokens.LocalConfigRuntimeState, this.constructor.name);
        this.chartManager = patchInject(chartManager, InjectTokens.ChartManager, this.constructor.name);
    }
    static consensusNodeSkipConditionCallback(nodeComponent) {
        return (nodeComponent.metadata.phase === DeploymentPhase.REQUESTED ||
            nodeComponent.metadata.phase === DeploymentPhase.STOPPED);
    }
    static componentValidationsMapping = {
        relayNodes: {
            displayName: 'Relay Nodes',
            getLabelsCallback: Templates.renderRelayLabels,
            legacyReleaseName: constants.JSON_RPC_RELAY_RELEASE_NAME,
        },
        haProxies: {
            displayName: 'HaProxy',
            getLabelsCallback: Templates.renderHaProxyLabels,
        },
        mirrorNodes: {
            displayName: 'Mirror Node',
            getLabelsCallback: Templates.renderMirrorNodeLabels,
            legacyReleaseName: constants.MIRROR_NODE_RELEASE_NAME,
        },
        envoyProxies: {
            displayName: 'Envoy Proxy',
            getLabelsCallback: Templates.renderEnvoyProxyLabels,
        },
        explorers: {
            displayName: 'Explorer',
            getLabelsCallback: Templates.renderExplorerLabels,
            legacyReleaseName: 'hiero-explorer',
        },
        consensusNodes: {
            displayName: 'Consensus Node',
            getLabelsCallback: Templates.renderConsensusNodeLabels,
            skipCondition: RemoteConfigValidator_1.consensusNodeSkipConditionCallback,
        },
        blockNodes: {
            displayName: 'Block Node',
            getLabelsCallback: Templates.renderBlockNodeLabels,
            legacyReleaseName: `${constants.BLOCK_NODE_RELEASE_NAME}-0`,
        },
    };
    async validateComponents(namespace, skipConsensusNodes, state) {
        const validationPromises = Object.entries(RemoteConfigValidator_1.componentValidationsMapping)
            .filter(([key]) => key !== 'consensusNodes' || !skipConsensusNodes)
            .flatMap(([key, { getLabelsCallback, displayName, skipCondition, legacyReleaseName }]) => this.validateComponentGroup(key, namespace, state[key], getLabelsCallback, displayName, skipCondition, legacyReleaseName));
        await Promise.all(validationPromises);
    }
    validateComponentGroup(key, namespace, components, getLabelsCallback, displayName, skipCondition, legacyReleaseName) {
        return components.map(async (component) => {
            if (skipCondition?.(component)) {
                return;
            }
            const context = this.localConfig.configuration.clusterRefs.get(component.metadata.cluster)?.toString();
            let useLegacyReleaseName = false;
            if (legacyReleaseName && component.metadata.id <= 1) {
                if (key === 'relayNodes') {
                    const nodeAliases = component?.consensusNodeIds.map((nodeId) => Templates.renderNodeAliasFromNumber(nodeId + 1));
                    legacyReleaseName = `${legacyReleaseName}-${nodeAliases.join('-')}`;
                }
                const isLegacyChartInstalled = await this.chartManager.isChartInstalled(namespace, legacyReleaseName, context);
                if (isLegacyChartInstalled) {
                    useLegacyReleaseName = true;
                }
            }
            const labels = useLegacyReleaseName
                ? getLabelsCallback(component.metadata.id, legacyReleaseName)
                : getLabelsCallback(component.metadata.id);
            try {
                const pods = await this.k8Factory.getK8(context).pods().list(namespace, labels);
                if (pods.length === 0) {
                    throw new Error('Pod not found'); // to return the generic error message
                }
            }
            catch (error) {
                throw RemoteConfigValidator_1.buildValidationError(displayName, component, error, labels);
            }
        });
    }
    /**
     * Generic handler that throws errors.
     *
     * @param displayName - name to display in error message
     * @param component - component which is not found in the cluster
     * @param error - original error for the kube client
     * @param labels - labels used to find the component
     */
    static buildValidationError(displayName, component, error, labels) {
        return new SoloError(RemoteConfigValidator_1.buildValidationErrorMessage(displayName, component, labels), error, component);
    }
    static buildValidationErrorMessage(displayName, component, labels = []) {
        let message = `${displayName} in remote config with id ${component.metadata.id} was not found in ` +
            `namespace: ${component.metadata.namespace}, ` +
            `cluster: ${component.metadata.cluster}`;
        if (labels?.length !== 0) {
            message += `,    labels: ${labels}`;
        }
        return message;
    }
};
RemoteConfigValidator = RemoteConfigValidator_1 = __decorate([
    injectable(),
    __param(0, inject(InjectTokens.K8Factory)),
    __param(1, inject(InjectTokens.LocalConfigRuntimeState)),
    __param(2, inject(InjectTokens.ChartManager)),
    __metadata("design:paramtypes", [Object, Function, Function])
], RemoteConfigValidator);
export { RemoteConfigValidator };
//# sourceMappingURL=remote-config-validator.js.map