"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getContainerByOrganization = exports.removeContainer = exports.createContainer = exports.stopContainer = exports.startContainer = exports.getAvailablePort = exports.getOrganizationBotPort = exports.existsContainer = exports.listContainers = void 0;
const dockerode_1 = __importDefault(require("dockerode"));
const docker = new dockerode_1.default();
/**
 * Listar todos los contenedores.
 */
const listContainers = async () => {
    return docker.listContainers({ all: true });
};
exports.listContainers = listContainers;
const existsContainer = async (organizationId) => {
    const contenedores = await (0, exports.listContainers)();
    const contenedoresNombres = Array.from(contenedores, (item) => item.Names[0].split("_bot")[0].substring(1));
    if (contenedoresNombres.includes(organizationId)) {
        return true;
    }
    return false;
};
exports.existsContainer = existsContainer;
const getOrganizationBotPort = async (organizationId) => {
    const contenedores = await (0, exports.listContainers)();
    for (const contenedor of contenedores) {
        if (contenedor.Names.includes(organizationId)) {
            const port = contenedor.Ports[0].PublicPort;
            return port;
        }
    }
    return -1;
};
exports.getOrganizationBotPort = getOrganizationBotPort;
const getAvailablePort = async () => {
    const contenedores = await (0, exports.listContainers)();
    let defaultPort = process.env.DEFAULT_BOT_START_PORT ? parseInt(process.env.DEFAULT_BOT_START_PORT) : -1;
    if (contenedores.length == 0) {
        return defaultPort;
    }
    contenedores.sort((a, b) => b.Created - a.Created);
    //Obtengo el contenedor mas reciente.
    const lastContainerCreated = contenedores.shift();
    if (!lastContainerCreated) {
        return defaultPort;
    }
    const lastPort = lastContainerCreated.Ports;
    if (!lastPort) {
        return defaultPort;
    }
    if (lastPort.length == 0) {
        return defaultPort;
    }
    return lastPort[0].PublicPort + 1;
};
exports.getAvailablePort = getAvailablePort;
/**
 * Iniciar un contenedor por ID.
 */
const startContainer = async (containerId) => {
    const container = docker.getContainer(containerId);
    await container.start();
};
exports.startContainer = startContainer;
/**
 * Detener un contenedor por ID.
 */
const stopContainer = async (containerId) => {
    const container = docker.getContainer(containerId);
    await container.stop();
};
exports.stopContainer = stopContainer;
const createContainer = async (port, name, image) => {
    try {
        // Crear un contenedor con las configuraciones especificadas
        const container = await docker.createContainer({
            Image: image,
            name,
            Env: [`PORT=${port}`],
            ExposedPorts: {
                [`${port}/tcp`]: {}, // Define el puerto expuesto
            },
            HostConfig: {
                PortBindings: {
                    [`${port}/tcp`]: [{ HostPort: `${port}` }], // Mapea el puerto entre el host y el contenedor
                },
            },
        });
        // Iniciar el contenedor creado
        await container.start();
        // Devolver el ID del contenedor como resultado
        return container.id;
    }
    catch (error) {
        throw new Error(`Error al crear el contenedor: ${error.message}`);
    }
};
exports.createContainer = createContainer;
const removeContainer = async (containerId) => {
    try {
        // Obtiene el contenedor por su ID
        const container = docker.getContainer(containerId);
        // Verifica si el contenedor existe antes de intentar eliminarlo
        const containerInfo = await container.inspect();
        if (containerInfo.State.Running) {
            // Si el contenedor está corriendo, debe detenerse primero
            await container.stop();
        }
        // Elimina el contenedor
        await container.remove();
    }
    catch (error) {
        throw new Error(`Error al eliminar el contenedor: ${error.message}`);
    }
};
exports.removeContainer = removeContainer;
const getContainerByOrganization = async (organizationId) => {
    const contenedores = await (0, exports.listContainers)();
    for (const contenedor of contenedores) {
        if (contenedor.Names.some((item) => item.includes(organizationId))) {
            return contenedor;
        }
    }
    throw new Error("Container not found");
};
exports.getContainerByOrganization = getContainerByOrganization;
