import { Router } from "express";
import {
    createContainer,
    listContainers,
    removeContainer,
    startContainer,
    stopContainer,
    getAvailablePort,
    existsContainer,
    getContainerByOrganization,
} from "../services/dockerService";
import axios from "axios";

export enum BOT_STATE {
    "EXISTS" = "exists",
    "NOT_EXISTS" = "not_exists",
}

export enum SERVER_STATE {
    "RUNNING" = "running",
    "NOT_WORKING" = "not_working",
}

const router = Router();

const getContainerApiUrl = (name: string, port: string): string => {
    const isProduction = process.env.NODE_ENV === "production";
    const baseUrl = isProduction ? name : "localhost";
    const url = `http:/${baseUrl}:${port}/`;
    return url;
};

// Obtener todos los contenedores
router.get("/", async (req, res) => {
    try {
        const containers = await listContainers();
        res.json(containers);
    } catch (error: any) {
        res.status(500).json({ error: error.message });
    }
});

// Iniciar un contenedor por ID
router.post("/:id/start", async (req, res) => {
    try {
        const organizationId = req.params.id;
        const containerInfo = await getContainerByOrganization(organizationId);
        await startContainer(containerInfo.Id);
        res.json({ message: `El bot ${containerInfo.Id} ha sido iniciado` });
    } catch (error: any) {
        if (error.message.indexOf("already started") >= 0) {
            res.json({ message: `El bot se encontraba iniciado anteriormente.` });
            return;
        }
        res.status(500).json({ error: error.message });
    }
});

// Obtener el QR de conexion para el bot de una organization.
router.get("/:id/qr", async (req, res) => {
    try {
        const organizationId = req.params.id;
        const containerInfo = await getContainerByOrganization(organizationId);
        const containerName = containerInfo.Names[0].toString();
        const containerPort = containerInfo.Ports[0].PublicPort.toString();
        const url = getContainerApiUrl(containerName, containerPort);
        const response = await axios.get(url, { responseType: "arraybuffer" });
        res.setHeader("Content-type", "image/png");
        res.send(response.data);
    } catch (error: any) {
        res.status(500).json({ error: error.message });
    }
});

// Detener un contenedor por ID
router.post("/:id/stop", async (req, res) => {
    try {
        const organizationId = req.params.id;
        const containerInfo = await getContainerByOrganization(organizationId);
        await stopContainer(containerInfo.Id);
        res.json({ message: `El bot de la organizacion ${organizationId} ha sido detenido` });
    } catch (error: any) {
        console.log(error.message);
        res.status(500).json({ error: error.message });
    }
});

// Eliminar un contenedor por ID
router.delete("/:id", async (req, res) => {
    try {
        const organizationId = req.params.id;
        const containerInfo = await getContainerByOrganization(organizationId);
        await removeContainer(containerInfo.Id);
        res.json({ message: `El bot de la organizacion ${organizationId} removed` });
    } catch (error: any) {
        res.status(500).json({ error: error.message });
    }
});

// Crear un nuevo contenedor
router.post("/create", async (req, res) => {
    try {
        const { organizationId } = req.body;
        const port = await getAvailablePort();

        if (!port) {
            res.status(400).json({ error: "Port is required" });
            return;
        }

        if (await existsContainer(organizationId)) {
            res.json({ message: `Ya existe un bot de whatsapp creado para esta organizacion` });
            return;
        }

        const containerName = `${organizationId}_bot_${port}`;
        const imageName = "txbot";

        const containerId = await createContainer(port, containerName, imageName);
        console.log(
            `Se ha creado un nuevo bot en el contenedor ${containerId} para la organizacion ${organizationId}`
        );
        res.json({ message: `El bot ha sido creado con exito`, port, organizationId });
    } catch (error: any) {
        res.status(500).json({ error: error.message });
    }
});

// Consultar el estado de un contenedor par auna organizationId
router.post("/:id/status", async (req, res) => {
    try {
        const organizationId = req.params.id;
        const info = await getContainerByOrganization(organizationId);
        res.json({
            state: BOT_STATE.EXISTS,
            status: info.Status,
            serverState: SERVER_STATE.RUNNING,
        });
    } catch (error: any) {
        res.status(500).json({ error: error.message, code: 404 });
    }
});

export interface MessageData {
    number: string;
    message: string;
}

router.post("/:id/send", async (req, res) => {
    try {
        const organizationId = req.params.id;
        const data = req.body as MessageData;
        const info = await getContainerByOrganization(organizationId);
        const containerName = info.Names[0].toString();
        const containerPort = info.Ports[0].PublicPort.toString();
        const url = getContainerApiUrl(containerName, containerPort);
        const result = await axios.post(url + "v1/messages", data);

        if (result.status !== 200) {
            throw new Error("Ha ocurrido un error al enviar el mensaje" + result);
        }

        res.json({ message: `Mensaje enviado` });
    } catch (error: any) {
        res.status(500).json({ error: error.message });
    }
});

router.post("/:id/session", async (req, res) => {
    try {
        const organizationId = req.params.id;
        const data = req.body as MessageData;
        const info = await getContainerByOrganization(organizationId);

        const containerName = info.Names[0].toString();
        const containerPort = info.Ports[0].PublicPort.toString();
        const url = getContainerApiUrl(containerName, containerPort);

        const result = await axios.post(url + "v1/session", data);

        if (result.status !== 200) {
            throw new Error("Ha ocurrido un error al enviar el mensaje" + result);
        }

        const resultData = result.data;

        res.json({ message: `${resultData}` });
    } catch (error: any) {
        console.log(error);
        res.status(500).json({ error: error.message });
    }
});

export default router;
