"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.remove = exports.update = exports.show = exports.store = exports.weebhook = exports.media = exports.whatsAppOfficialMatchQueueUser = exports.whatsAppOfficialMatchQueue = exports.index = void 0;
const socket_1 = require("../libs/socket");
const wbot_1 = require("../libs/wbot");
const DeleteDirectory_1 = require("../helpers/DeleteDirectory");
const CreateWhatsAppService_1 = __importDefault(require("../services/WhatsappService/CreateWhatsAppService"));
const DeleteWhatsAppService_1 = __importDefault(require("../services/WhatsappService/DeleteWhatsAppService"));
const ListWhatsAppsService_1 = __importDefault(require("../services/WhatsappService/ListWhatsAppsService"));
const ShowWhatsAppService_1 = __importDefault(require("../services/WhatsappService/ShowWhatsAppService"));
const UpdateWhatsAppService_1 = __importDefault(require("../services/WhatsappService/UpdateWhatsAppService"));
const AppError_1 = __importDefault(require("../errors/AppError"));
const GetNumberSequence_1 = __importDefault(require("../helpers/GetNumberSequence"));
const path_1 = __importStar(require("path"));
const ValidatePhoneName_1 = __importDefault(require("../helpers/ValidatePhoneName"));
const AxiosPost_1 = __importDefault(require("../helpers/AxiosPost"));
const Whatsapp_1 = __importDefault(require("../models/Whatsapp"));
const wbotMessageListener_1 = require("../services/WbotServices/wbotMessageListener");
const GetDefaultWhatsApp_1 = __importDefault(require("../helpers/GetDefaultWhatsApp"));
const ShowUserService_1 = __importDefault(require("../services/UserServices/ShowUserService"));
const fs_1 = __importDefault(require("fs"));
const ReceiveWhatsAppMediaOfficialAPI_1 = __importDefault(require("../helpers/ReceiveWhatsAppMediaOfficialAPI"));
const WhatsappOfficialNumberInfo_1 = __importDefault(require("../helpers/WhatsappOfficialNumberInfo"));
const WhaticketSettings_1 = require("../helpers/WhaticketSettings");
const ListWhatsAppsNumber_1 = __importDefault(require("../services/WhatsappService/ListWhatsAppsNumber"));
const SettingTicket_1 = __importDefault(require("../models/SettingTicket"));
const sequelize_1 = require("sequelize");
const RedisClient_1 = require("../helpers/RedisClient");
let count = 0;
const index = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    var _a;
    let whatsapps = yield ListWhatsAppsService_1.default();
    if (((_a = WhaticketSettings_1.getSettingValue("whatsaAppCloudApi")) === null || _a === void 0 ? void 0 : _a.value) == "enabled") {
        // Atualizar isso quando tiver tempo
        if (count > 12)
            count = 0;
        if (count == 0) {
            for (let i in whatsapps) {
                const { id, wabaId, isOfficial } = whatsapps[i];
                if (isOfficial && wabaId) {
                    try {
                        const info = yield WhatsappOfficialNumberInfo_1.default(wabaId);
                        if (info) {
                            const whatsapp = yield Whatsapp_1.default.findByPk(id);
                            if (whatsapp) {
                                whatsapp.update({
                                    classification: info.quality_rating
                                });
                                whatsapps[i].classification = info.quality_rating;
                            }
                        }
                    }
                    catch (error) {
                        console.log("error on try update classification number from oficial whatsapp in WhatsappController.ts: ", error);
                    }
                }
            }
        }
        console.log("count: ", count);
        count++;
    }
    return res.status(200).json(whatsapps);
});
exports.index = index;
const whatsAppOfficialMatchQueue = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    const { userId, queueId } = req.query;
    let whatsapps = yield GetDefaultWhatsApp_1.default({ userId, queueId });
    if (whatsapps && Array.isArray(whatsapps)) {
        const uniqueWhatsApps = whatsapps.filter((whatsapp, index, self) => index === self.findIndex(w => w.number === whatsapp.number));
        whatsapps = uniqueWhatsApps;
    }
    return res.status(200).json(whatsapps);
});
exports.whatsAppOfficialMatchQueue = whatsAppOfficialMatchQueue;
const whatsAppOfficialMatchQueueUser = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    const { userId, queueId } = req.query;
    let whatsApps = yield ListWhatsAppsService_1.default();
    let user = yield ShowUserService_1.default(userId);
    // console.log(JSON.stringify(user, null, 2));
    let queuesConnected = whatsApps
        .filter((w) => w.status === "CONNECTED")
        .map((item) => {
        const { queues } = item;
        return {
            queues: queues.map((q) => {
                return { id: q.id };
            })
        };
    })
        .flatMap((item) => item.queues.map((queue) => queue.id));
    queuesConnected = [...new Set(queuesConnected)].map(q => {
        return { id: q };
    });
    const userQueues = user.queues.map((item) => {
        const { id, name, color } = item;
        return {
            id,
            name,
            color,
            disable: queuesConnected.find((queue) => queue.id === id)
                ? false
                : true
        };
    });
    return res.status(200).json(userQueues);
});
exports.whatsAppOfficialMatchQueueUser = whatsAppOfficialMatchQueueUser;
const media = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    const { filename } = req.params;
    const filePath = path_1.join(__dirname, "..", "..", "..", "..", "public", filename);
    console.log("filePath: ", filePath);
    console.log(filename);
    if (!fs_1.default.existsSync(filePath)) {
        return res.status(404).json({ message: "File not folund!" });
    }
    // Set appropriate headers for the download.
    res.setHeader("Content-Disposition", `attachment; filename=${filename}`);
    res.sendFile(filePath);
});
exports.media = media;
const weebhook = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    // console.log(JSON.stringify(req.body, null, 2));
    var _b, _c, _d;
    console.log("req.method: ", req.method);
    if (req.method == "GET") {
        /**
         * UPDATE YOUR VERIFY TOKEN
         *This will be the Verify Token value when you set up webhook
         **/
        const verify_token = process.env.VERIFY_TOKEN;
        // Parse params from the webhook verification request
        let mode = req.query["hub.mode"];
        let token = req.query["hub.verify_token"];
        let challenge = req.query["hub.challenge"];
        // Check if a token and mode were sent
        if (mode && token) {
            // Check the mode and token sent are correct
            if (mode === "subscribe" && token === verify_token) {
                // Respond with 200 OK and challenge token from the request
                console.log("WEBHOOK_VERIFIED");
                return res.status(200).send(challenge);
            }
            else {
                // Responds with '403 Forbidden' if verify tokens do not match
                return res.sendStatus(403);
            }
        }
        return res.sendStatus(500);
    }
    // MESSAGE
    if (req.body.object) {
        if (req.body.entry &&
            req.body.entry[0].changes &&
            req.body.entry[0].changes[0] &&
            req.body.entry[0].changes[0].value.messages &&
            req.body.entry[0].changes[0].value.messages[0]) {
            const message = req.body.entry[0].changes[0].value.messages[0];
            const contact_from = message.from; // extract the phone number from the webhook payload
            const contact_to = req.body.entry[0].changes[0].value.metadata.display_phone_number;
            let type = message.type;
            const contact_to_exist = yield RedisClient_1.get({
                key: "whatsapp:*",
                value: `${contact_to}`
            });
            if (contact_to_exist == null) {
                console.log("WHATSAPP OFFICIAL", " | CONCTACT_FROM: ", contact_from, " | CONTACT_TO: ", contact_to);
                console.log("NUMBER IGNORED. WHATSAPP NUMBER FROM ANOTHER OMNIHIT APPLICATION!");
                return res.status(403).json({ error: "Unauthorized" });
            }
            let wbot = {};
            let msg = {};
            let contacts = req.body.entry[0].changes[0].value.contacts[0];
            msg = Object.assign(Object.assign({}, msg), { id: { id: message.id }, fromMe: false, type: type, read: false, hasMedia: false });
            // NEW
            const whatsapp = yield ShowWhatsAppService_1.default(null, {
                number: contact_to
            });
            if (type == "text") {
                if (!((_b = message === null || message === void 0 ? void 0 : message.text) === null || _b === void 0 ? void 0 : _b.body)) {
                    return res.status(400).json({ error: "body not found" });
                }
                type = "chat";
                msg = Object.assign(Object.assign({}, msg), { body: message.text.body, // extract the message text from the webhook payload,
                    type });
            }
            else {
                if (!((_c = message[message === null || message === void 0 ? void 0 : message.type]) === null || _c === void 0 ? void 0 : _c.id)) {
                    return res.status(400).json({ error: "id not found" });
                }
                const mediaId = message[message.type].id;
                const mimetype = message[message.type].mime_type;
                let filename = yield ReceiveWhatsAppMediaOfficialAPI_1.default(mediaId, whatsapp.phoneNumberId);
                if (!filename)
                    throw new AppError_1.default("There was an error");
                msg = Object.assign(Object.assign({}, msg), { hasMedia: true });
                wbot = Object.assign(Object.assign({}, wbot), { media: { filename, mimetype } });
            }
            msg = Object.assign(Object.assign({}, msg), { phoneNumberId: whatsapp.phoneNumberId });
            console.log("from: ", contact_from);
            console.log("to: ", contact_to);
            console.log("msg type: ", type);
            wbot = Object.assign(Object.assign({}, wbot), { id: whatsapp.id, msgContact: {
                    number: contact_from,
                    name: (_d = contacts === null || contacts === void 0 ? void 0 : contacts.profile) === null || _d === void 0 ? void 0 : _d.name
                }, chat: { isGroup: false, unreadCount: 1 }, quotedMsg: message && (message === null || message === void 0 ? void 0 : message.context) ? message.context.id : undefined });
            wbotMessageListener_1.handleMessage(msg, wbot, true);
            return res.sendStatus(200);
        }
        // STATUS MESSAGE SENT
        else if (req.body.entry &&
            req.body.entry[0].changes &&
            req.body.entry[0].changes[0] &&
            req.body.entry[0].changes[0].value.statuses &&
            req.body.entry[0].changes[0].value.statuses[0]) {
            const id = req.body.entry[0].changes[0].value.statuses[0].id;
            const ack = req.body.entry[0].changes[0].value.statuses[0].status;
            wbotMessageListener_1.handleMsgAck(id, ack, true);
        }
    }
    return res.sendStatus(200);
});
exports.weebhook = weebhook;
const store = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    let { name, status, isDefault, greetingMessage, farewellMessage, queueIds, url, urlApi, phoneNumberId, wabaId, isOfficial, number } = req.body;
    if (req.user.profile !== "master") {
        throw new AppError_1.default("ERR_NO_PERMISSION", 403);
    }
    const invalid = checkWhatsAppData({
        urlApi,
        isOfficial,
        phoneNumberId,
        wabaId,
        number
    });
    if (invalid) {
        return res.status(400).json(invalid);
    }
    if (isOfficial) {
        urlApi = "";
        url = "";
    }
    else if (!isOfficial) {
        phoneNumberId = "";
        wabaId = "";
        number = "";
    }
    let invalidPhoneName = ValidatePhoneName_1.default(name);
    if (invalidPhoneName) {
        return res.status(200).json({ message: invalidPhoneName });
    }
    const { whatsapp, oldDefaultWhatsapp } = yield CreateWhatsAppService_1.default({
        name,
        url,
        urlApi,
        status,
        isDefault,
        greetingMessage,
        farewellMessage,
        queueIds,
        phoneNumberId,
        wabaId,
        isOfficial,
        number
    });
    console.log("whatsapp.id: ", whatsapp.id);
    if (!isOfficial) {
        AxiosPost_1.default(`${whatsapp.urlApi}/api/session`, {
            app_name: process.env.APP_NAME,
            whatsappId: whatsapp.id,
            number: GetNumberSequence_1.default(name),
            client_url: `${process.env.BACKEND_URL_RAW}:${process.env.PORT}`
        });
    }
    else {
        yield RedisClient_1.set(`whatsapp:${whatsapp.id}`, JSON.stringify({
            number: whatsapp === null || whatsapp === void 0 ? void 0 : whatsapp.number,
            id: whatsapp === null || whatsapp === void 0 ? void 0 : whatsapp.id,
            greetingMessage: whatsapp === null || whatsapp === void 0 ? void 0 : whatsapp.greetingMessage,
            phoneNumberId: whatsapp === null || whatsapp === void 0 ? void 0 : whatsapp.phoneNumberId
        }));
    }
    const io = socket_1.getIO();
    io.emit("whatsapp", {
        action: "update",
        whatsapp
    });
    if (oldDefaultWhatsapp) {
        io.emit("whatsapp", {
            action: "update",
            whatsapp: oldDefaultWhatsapp
        });
    }
    return res.status(200).json(whatsapp);
});
exports.store = store;
const show = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    const { whatsappId } = req.params;
    const whatsapp = yield ShowWhatsAppService_1.default(whatsappId);
    return res.status(200).json(whatsapp);
});
exports.show = show;
const update = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    const { whatsappId } = req.params;
    const whatsappData = req.body;
    let invalidPhoneName = ValidatePhoneName_1.default(whatsappData.name);
    if (invalidPhoneName) {
        return res.status(200).json({ message: invalidPhoneName });
    }
    const { urlApi, isOfficial, phoneNumberId, number, wabaId } = whatsappData;
    const invalid = checkWhatsAppData({
        urlApi,
        isOfficial,
        phoneNumberId,
        wabaId,
        number
    });
    if (invalid) {
        return res.status(400).json(invalid);
    }
    if (isOfficial) {
        whatsappData.urlApi = "";
        whatsappData.url = "";
    }
    else if (!isOfficial) {
        whatsappData.phoneNumberId = "";
        whatsappData.wabaId = "";
        whatsappData.number = "";
    }
    const { whatsapp, oldDefaultWhatsapp } = yield UpdateWhatsAppService_1.default({
        whatsappData,
        whatsappId
    });
    if (!(whatsappData === null || whatsappData === void 0 ? void 0 : whatsappData.isOfficial)) {
        AxiosPost_1.default(`${whatsapp.urlApi}/api/session`, {
            app_name: process.env.APP_NAME,
            whatsappId: whatsapp.id,
            number: GetNumberSequence_1.default(whatsapp.name),
            client_url: `${process.env.BACKEND_URL_RAW}:${process.env.PORT}`
        });
    }
    else {
        yield RedisClient_1.set(`whatsapp:${whatsapp.id}`, JSON.stringify({
            number: whatsapp === null || whatsapp === void 0 ? void 0 : whatsapp.number,
            id: whatsapp === null || whatsapp === void 0 ? void 0 : whatsapp.id,
            greetingMessage: whatsapp === null || whatsapp === void 0 ? void 0 : whatsapp.greetingMessage,
            phoneNumberId: whatsapp === null || whatsapp === void 0 ? void 0 : whatsapp.phoneNumberId
        }));
    }
    const io = socket_1.getIO();
    io.emit("whatsapp", {
        action: "update",
        whatsapp
    });
    if (oldDefaultWhatsapp) {
        io.emit("whatsapp", {
            action: "update",
            whatsapp: oldDefaultWhatsapp
        });
    }
    return res.status(200).json(whatsapp);
});
exports.update = update;
const remove = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    var _e, _f, _g;
    if (req.user.profile !== "master") {
        throw new AppError_1.default("ERR_NO_PERMISSION", 403);
    }
    const { whatsappId } = req.params;
    const whatsapp = yield Whatsapp_1.default.findByPk(whatsappId, { raw: true });
    if (!(whatsapp === null || whatsapp === void 0 ? void 0 : whatsapp.isOfficial)) {
        AxiosPost_1.default(`${whatsapp.urlApi}/api/session/del`, {
            app_name: process.env.APP_NAME,
            whatsappId: whatsappId
        });
    }
    yield RedisClient_1.del(`whatsapp:${whatsappId}`);
    let whats = yield ListWhatsAppsNumber_1.default(whatsappId);
    //  Remove tickets business hours config
    if (((_e = whats === null || whats === void 0 ? void 0 : whats.whatsapps) === null || _e === void 0 ? void 0 : _e.length) == 1) {
        const configIds = yield SettingTicket_1.default.findAll({
            where: { number: (_f = whats === null || whats === void 0 ? void 0 : whats.whatsapps[0]) === null || _f === void 0 ? void 0 : _f.number },
            raw: true,
            attributes: ["id"]
        });
        const whatsappTicketConfig = yield SettingTicket_1.default.findOne({
            where: { number: whats.whatsapps[0].number }
        });
        if (whatsappTicketConfig) {
            try {
                yield SettingTicket_1.default.destroy({
                    where: {
                        id: {
                            [sequelize_1.Op.in]: configIds.map(config => config.id)
                        }
                    }
                });
            }
            catch (error) {
                console.log("Error on delete SettingTicket by number: ", (_g = whats === null || whats === void 0 ? void 0 : whats.whatsapps[0]) === null || _g === void 0 ? void 0 : _g.number);
            }
        }
    }
    yield DeleteWhatsAppService_1.default(whatsappId);
    DeleteDirectory_1.removeDir(path_1.default.join(process.cwd(), ".wwebjs_auth", `session-bd_${whatsappId}`));
    DeleteDirectory_1.removeDir(path_1.default.join(process.cwd(), ".wwebjs_auth", "sessions", `session-bd_${whatsappId}`));
    wbot_1.removeWbot(+whatsappId);
    const io = socket_1.getIO();
    io.emit("whatsapp", {
        action: "delete",
        whatsappId: +whatsappId
    });
    return res.status(200).json({ message: "Whatsapp deleted." });
});
exports.remove = remove;
const checkWhatsAppData = ({ urlApi, isOfficial, phoneNumberId, wabaId, number }) => {
    if (isOfficial && (!phoneNumberId || phoneNumberId.trim() == "")) {
        return { message: "Phone number Id is required!" };
    }
    else if (isOfficial && (!wabaId || wabaId.trim() == "")) {
        return { message: "WABA ID is required!" };
    }
    else if (isOfficial && (!number || number.trim() == "")) {
        return { message: "Phone number is required!" };
    }
    else if (!isOfficial && (!urlApi || urlApi.trim() == "")) {
        return { message: "urlApi is required!" };
    }
};
