// SPDX-License-Identifier: Apache-2.0
import { V1Lease, V1LeaseSpec, V1MicroTime, V1ObjectMeta, } from '@kubernetes/client-node';
import { container } from 'tsyringe-neo';
import { InjectTokens } from '../../../../../core/dependency-injection/inject-tokens.js';
import { K8ClientLease } from './k8-client-lease.js';
import { ResourceReadError } from '../../../errors/resource-operation-errors.js';
import { ResourceType } from '../../../resources/resource-type.js';
import { sleep } from '../../../../../core/helpers.js';
import { Duration } from '../../../../../core/time/duration.js';
import { getReasonPhrase, StatusCodes } from 'http-status-codes';
import { KubeApiResponse } from '../../../kube-api-response.js';
import { ResourceOperation } from '../../../resources/resource-operation.js';
export class K8ClientLeases {
    coordinationApiClient;
    logger;
    constructor(coordinationApiClient) {
        this.coordinationApiClient = coordinationApiClient;
        this.logger = container.resolve(InjectTokens.SoloLogger);
    }
    async create(namespace, leaseName, holderName, durationSeconds) {
        const lease = new V1Lease();
        const metadata = new V1ObjectMeta();
        metadata.name = leaseName;
        metadata.namespace = namespace.name;
        lease.metadata = metadata;
        const spec = new V1LeaseSpec();
        spec.holderIdentity = holderName;
        spec.leaseDurationSeconds = durationSeconds;
        spec.acquireTime = new V1MicroTime();
        lease.spec = spec;
        let result;
        try {
            result = await this.coordinationApiClient.createNamespacedLease({ namespace: namespace.name, body: lease });
        }
        catch (error) {
            KubeApiResponse.throwError(error, ResourceOperation.CREATE, ResourceType.LEASE, namespace, leaseName);
        }
        return K8ClientLease.fromV1Lease(result);
    }
    async delete(namespace, name) {
        let result;
        try {
            result = await this.coordinationApiClient.deleteNamespacedLease({ name, namespace: namespace.name });
        }
        catch (error) {
            KubeApiResponse.throwError(error, ResourceOperation.DELETE, ResourceType.LEASE, namespace, name);
        }
        return result;
    }
    async read(namespace, leaseName, timesCalled = 0) {
        let result;
        try {
            result = await this.coordinationApiClient.readNamespacedLease({ name: leaseName, namespace: namespace.name });
        }
        catch (error) {
            if (error.code === StatusCodes.INTERNAL_SERVER_ERROR && timesCalled < 4) {
                // could be k8s control plane has no resources available
                this.logger.debug(`Retrying readNamespacedLease(${leaseName}, ${namespace}) in 5 seconds because of ${getReasonPhrase(StatusCodes.INTERNAL_SERVER_ERROR)}`);
                await sleep(Duration.ofSeconds(5));
                try {
                    return await this.read(namespace, leaseName, timesCalled + 1);
                }
                catch (error) {
                    throw new ResourceReadError(ResourceType.LEASE, namespace, leaseName, error);
                }
            }
            else {
                throw new ResourceReadError(ResourceType.LEASE, namespace, leaseName, error);
            }
        }
        return K8ClientLease.fromV1Lease(result);
    }
    async renew(namespace, leaseName, lease) {
        const v1Lease = K8ClientLease.toV1Lease(lease);
        v1Lease.spec.renewTime = new V1MicroTime();
        let result;
        try {
            result = await this.coordinationApiClient.replaceNamespacedLease({
                name: leaseName,
                namespace: namespace.name,
                body: v1Lease,
            });
        }
        catch (error) {
            KubeApiResponse.throwError(error, ResourceOperation.REPLACE, ResourceType.LEASE, namespace, leaseName);
        }
        return K8ClientLease.fromV1Lease(result);
    }
    async transfer(lease, newHolderName) {
        const v1Lease = K8ClientLease.toV1Lease(lease);
        v1Lease.spec.leaseTransitions++;
        v1Lease.spec.renewTime = new V1MicroTime();
        v1Lease.spec.holderIdentity = newHolderName;
        let result;
        try {
            result = await this.coordinationApiClient.replaceNamespacedLease({
                name: v1Lease.metadata.name,
                namespace: v1Lease.metadata.namespace,
                body: v1Lease,
            });
        }
        catch (error) {
            KubeApiResponse.throwError(error, ResourceOperation.REPLACE, ResourceType.LEASE, lease.namespace, v1Lease.metadata.name);
        }
        return K8ClientLease.fromV1Lease(result);
    }
}
//# sourceMappingURL=k8-client-leases.js.map