// SPDX-License-Identifier: Apache-2.0
import { V1ConfigMap, V1ObjectMeta } from '@kubernetes/client-node';
import { ResourceCreateError, ResourceDeleteError, ResourceNotFoundError, ResourceReplaceError, ResourceUpdateError, } from '../../../errors/resource-operation-errors.js';
import { ResourceType } from '../../../resources/resource-type.js';
import { ResourceOperation } from '../../../resources/resource-operation.js';
import { KubeApiResponse } from '../../../kube-api-response.js';
import { SoloError } from '../../../../../core/errors/solo-error.js';
import { container } from 'tsyringe-neo';
import { K8ClientConfigMap } from './k8-client-config-map.js';
import { InjectTokens } from '../../../../../core/dependency-injection/inject-tokens.js';
export class K8ClientConfigMaps {
    kubeClient;
    logger;
    constructor(kubeClient) {
        this.kubeClient = kubeClient;
        this.logger = container.resolve(InjectTokens.SoloLogger);
    }
    async create(namespace, name, labels, data) {
        return await this.createOrReplaceWithForce(namespace, name, labels, data, false, true);
    }
    async createOrReplace(namespace, name, labels, data) {
        return await this.createOrReplaceWithForce(namespace, name, labels, data, false, false);
    }
    async delete(namespace, name) {
        try {
            const resp = await this.kubeClient.deleteNamespacedConfigMap(name, namespace.name);
            return KubeApiResponse.isFailingStatus(resp.response);
        }
        catch (error) {
            throw new ResourceDeleteError(ResourceType.CONFIG_MAP, namespace, name, error);
        }
    }
    async read(namespace, name) {
        const { response, body } = await this.kubeClient
            .readNamespacedConfigMap(name, namespace?.name)
            .catch((error) => error);
        KubeApiResponse.check(response, ResourceOperation.READ, ResourceType.CONFIG_MAP, namespace, name);
        return K8ClientConfigMap.fromV1ConfigMap(body);
    }
    async replace(namespace, name, labels, data) {
        return await this.createOrReplaceWithForce(namespace, name, labels, data, true, false);
    }
    async exists(namespace, name) {
        try {
            const cm = await this.read(namespace, name);
            return !!cm;
        }
        catch (error) {
            if (error instanceof ResourceNotFoundError) {
                return false;
            }
            else {
                throw error;
            }
        }
    }
    async createOrReplaceWithForce(namespace, name, labels, data, forceReplace, forceCreate) {
        const replace = await this.shouldReplace(namespace, name, forceReplace, forceCreate);
        const configMap = new V1ConfigMap();
        configMap.data = data;
        const metadata = new V1ObjectMeta();
        metadata.name = name;
        metadata.namespace = namespace.name;
        metadata.labels = labels;
        configMap.metadata = metadata;
        try {
            const resp = replace
                ? await this.kubeClient.replaceNamespacedConfigMap(name, namespace.name, configMap)
                : await this.kubeClient.createNamespacedConfigMap(namespace.name, configMap);
            return KubeApiResponse.isCreatedStatus(resp.response);
        }
        catch (error) {
            throw replace
                ? new ResourceReplaceError(ResourceType.CONFIG_MAP, namespace, name, error)
                : new ResourceCreateError(ResourceType.CONFIG_MAP, namespace, name, error);
        }
    }
    async shouldReplace(namespace, name, forceReplace, forceCreate) {
        if (forceReplace && !forceCreate) {
            return true;
        }
        if (forceCreate) {
            return false;
        }
        return await this.exists(namespace, name);
    }
    async list(namespace, labels) {
        const labelsSelector = labels ? labels.join(',') : undefined;
        let results;
        try {
            results = await this.kubeClient.listNamespacedConfigMap(namespace.name, undefined, undefined, undefined, undefined, labelsSelector);
        }
        catch (error) {
            throw new SoloError('Failed to list config maps', error);
        }
        KubeApiResponse.check(results.response, ResourceOperation.LIST, ResourceType.CONFIG_MAP, namespace, '');
        return results?.body?.items?.map((v1ConfigMap) => K8ClientConfigMap.fromV1ConfigMap(v1ConfigMap)) || [];
    }
    async listForAllNamespaces(labels) {
        const labelsSelector = labels ? labels.join(',') : undefined;
        let results;
        try {
            results = await this.kubeClient.listConfigMapForAllNamespaces(undefined, undefined, undefined, labelsSelector);
        }
        catch (error) {
            throw new SoloError('Failed to list config maps for all namespaces', error);
        }
        KubeApiResponse.check(results.response, ResourceOperation.LIST, ResourceType.CONFIG_MAP, undefined, '');
        return results?.body?.items?.map((v1ConfigMap) => K8ClientConfigMap.fromV1ConfigMap(v1ConfigMap)) || [];
    }
    async update(namespace, name, data) {
        if (!(await this.exists(namespace, name))) {
            throw new ResourceNotFoundError(ResourceOperation.READ, ResourceType.CONFIG_MAP, namespace, name);
        }
        const patch = {
            data: data,
        };
        const options = {
            headers: { 'Content-Type': 'application/merge-patch+json' }, // Or the appropriate content type
        };
        let result;
        try {
            result = await this.kubeClient.patchNamespacedConfigMap(name, namespace.name, patch, undefined, // pretty
            undefined, // dryRun
            undefined, // fieldManager
            undefined, // fieldValidation
            undefined, // force
            options);
            this.logger.info(`Patched ConfigMap ${name} in namespace ${namespace}`);
        }
        catch (error) {
            throw new ResourceUpdateError(ResourceType.CONFIG_MAP, namespace, name, error);
        }
        KubeApiResponse.check(result.response, ResourceOperation.UPDATE, ResourceType.CONFIG_MAP, namespace, name);
        if (result.body) {
            return;
        }
        else {
            throw new SoloError(`Failed to patch ConfigMap ${name} in namespace ${namespace}, no config map returned from patch`);
        }
    }
}
//# sourceMappingURL=k8-client-config-maps.js.map