"use strict";
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.checkUserRight = exports.linkUserAndUserRight = exports.resetPassword = exports.updateUser = exports.checkUser = exports.listAllUsers = exports.deleteUser = exports.createUser = void 0;
const socket_1 = require("../libs/socket");
const sequelize_1 = require("sequelize");
const CreateUserService_1 = __importDefault(require("../services/UserServices/CreateUserService"));
const UpdateUserService_1 = __importDefault(require("../services/UserServices/UpdateUserService"));
const DeleteUserService_1 = __importDefault(require("../services/UserServices/DeleteUserService"));
const RedisClient_1 = require("../helpers/RedisClient");
const WhoIsOnlineMonitor_1 = require("../helpers/WhoIsOnlineMonitor");
const User_1 = __importDefault(require("../models/User"));
const createUser = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    const { user_id, user_first_name, user_tax_id, user_email, user_title } = req.body;
    const invalid = invalidProperties(req.body, [
        "user_id",
        "user_tax_id",
        "user_first_name"
    ]);
    if (invalid) {
        return res.status(400).json(response("1", `${invalid}`, "0", "createUser"));
    }
    const auxUser = yield User_1.default.findOne({ where: { secondaryId: user_id } });
    if (auxUser) {
        return res
            .status(400)
            .json(response("1", `The user ${user_id} already exist`, "0", "createUser"));
    }
    const user = yield CreateUserService_1.default({
        email: user_tax_id || user_email,
        password: "12345",
        name: user_first_name,
        profile: "user",
        ignoreThrow: true
    });
    if (user === null || user === void 0 ? void 0 : user.error) {
        return res
            .status(user === null || user === void 0 ? void 0 : user.status)
            .json(response("0", `${user === null || user === void 0 ? void 0 : user.msg}`, "0", "createUser"));
    }
    if (!(user === null || user === void 0 ? void 0 : user.error)) {
        const _user = yield User_1.default.findByPk(user.id);
        _user === null || _user === void 0 ? void 0 : _user.update({ secondaryId: user_id });
        const { id, name } = user;
        yield RedisClient_1.set(`user:${id}`, { id, name });
        const io = socket_1.getIO();
        io.emit("user", {
            action: "create",
            user
        });
        yield WhoIsOnlineMonitor_1.startWhoIsOnlineMonitor();
    }
    return res
        .status(200)
        .json(response("1", `User ${user_id} created`, "1", "createUser"));
});
exports.createUser = createUser;
const deleteUser = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    const { user_id } = req.body;
    const invalid = invalidProperties(req.body, ["user_id"]);
    if (invalid) {
        return res.status(400).json(response("1", `${invalid}`, "0", "deleteUser"));
    }
    const _user = yield User_1.default.findOne({ where: { secondaryId: user_id } });
    if (_user) {
        const user = yield DeleteUserService_1.default(_user.id, true);
        if (user === null || user === void 0 ? void 0 : user.error) {
            return res
                .status(user === null || user === void 0 ? void 0 : user.status)
                .json(response("0", `${user === null || user === void 0 ? void 0 : user.msg}`, "0", "deleteUser"));
        }
        if (!(user === null || user === void 0 ? void 0 : user.error)) {
            RedisClient_1.del(`user:${_user.id}`);
            const io = socket_1.getIO();
            io.emit("user", {
                action: "delete",
                userId: _user.id
            });
            yield WhoIsOnlineMonitor_1.stopWhoIsOnlineMonitor();
            io.emit("onlineStatus", {
                action: "delete",
                userOnlineTime: _user.id
            });
            yield WhoIsOnlineMonitor_1.startWhoIsOnlineMonitor();
            return res
                .status(200)
                .json(response("1", `User ${user_id} deleted`, "1", "deleteUser"));
        }
    }
    return res
        .status(500)
        .json(response("0", "Internal server error", "0", "deleteUser"));
});
exports.deleteUser = deleteUser;
const listAllUsers = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    const _users = yield User_1.default.findAll({
        where: {
            secondaryId: {
                [sequelize_1.Op.ne]: ""
            }
        },
        attributes: ["secondaryId", "name"]
    });
    if (_users) {
        const user_list = _users.map((user) => {
            const { secondaryId, name } = user;
            return { user_id: secondaryId, full_name: name };
        });
        return res
            .status(200)
            .json(response("1", "Success", user_list, "listAllUsers"));
    }
    return res
        .status(500)
        .json(response("0", "Internal server error", [], "listAllUsers"));
});
exports.listAllUsers = listAllUsers;
const checkUser = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    const { user_id } = req.body;
    const invalid = invalidProperties(req.body, ["user_id"]);
    if (invalid) {
        return res.status(400).json(response("1", `${invalid}`, "0", "checkUser"));
    }
    const _user = yield User_1.default.findOne({ where: { secondaryId: user_id } });
    if (_user) {
        return res
            .status(200)
            .json(response("1", `User ${user_id} exist`, "1", "checkUser"));
    }
    return res
        .status(404)
        .json(response("1", `User ${user_id} not exist`, "0", "checkUser"));
});
exports.checkUser = checkUser;
const updateUser = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    const { user_id, user_first_name, user_tax_id, user_email, user_title } = req.body;
    const invalid = invalidProperties(req.body, ["user_id"]);
    if (invalid) {
        return res.status(400).json(response("1", `${invalid}`, "0", "checkUser"));
    }
    const _user = yield User_1.default.findOne({ where: { secondaryId: user_id } });
    if (!_user)
        return res
            .status(404)
            .json(response("1", `User ${user_id} not exist`, "0", "updateUser"));
    const userData = {
        email: user_tax_id || user_email,
        name: user_first_name,
    };
    let user = yield UpdateUserService_1.default({
        userData,
        userId: _user.id,
        ignoreThrow: true
    });
    if (user === null || user === void 0 ? void 0 : user.error) {
        return res
            .status(user === null || user === void 0 ? void 0 : user.status)
            .json(response("0", `${user === null || user === void 0 ? void 0 : user.msg}`, "0", "updateUser"));
    }
    if (user) {
        const { id, name } = user;
        yield RedisClient_1.set(`user:${id}`, { id, name });
    }
    const io = socket_1.getIO();
    io.emit("user", {
        action: "update",
        user
    });
    return res
        .status(200)
        .json(response("1", `User ${user_id} updated`, "1", "updateUser"));
});
exports.updateUser = updateUser;
const resetPassword = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    const { user_id, user_password } = req.body;
    const invalid = invalidProperties(req.body, ["user_id", "user_password"]);
    if (invalid) {
        return res
            .status(400)
            .json(response("1", `${invalid}`, "0", "resetPassword"));
    }
    const _user = yield User_1.default.findOne({ where: { secondaryId: user_id } });
    if (!_user) {
        return res
            .status(404)
            .json(response("1", `User ${user_id} not exist`, "0", "resetPassword"));
    }
    const userData = {
        password: user_password,
        email: _user.email
    };
    let user = yield UpdateUserService_1.default({
        userData,
        userId: _user.id,
        ignoreThrow: true
    });
    if (user === null || user === void 0 ? void 0 : user.error) {
        return res
            .status(user === null || user === void 0 ? void 0 : user.status)
            .json(response("0", `${user === null || user === void 0 ? void 0 : user.msg}`, "0", "resetPassword"));
    }
    yield logoutUser(_user.id);
    return res
        .status(200)
        .json(response("1", `User ${user_id} password updated`, "1", "resetPassword"));
});
exports.resetPassword = resetPassword;
const linkUserAndUserRight = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    const { user_id, user_right_id, user_right_title } = req.body;
    const invalid = invalidProperties(req.body, ["user_id", "user_right_id"]);
    if (invalid) {
        return res
            .status(400)
            .json(response("1", `${invalid}`, "0", "linkUserAndUserRight"));
    }
    if ((user_right_id &&
        !["admin", "user", "supervisor"].includes(user_right_id === null || user_right_id === void 0 ? void 0 : user_right_id.trim().toLocaleLowerCase())) ||
        (user_right_title &&
            !["admin", "user", "supervisor"].includes(user_right_title === null || user_right_title === void 0 ? void 0 : user_right_title.trim().toLocaleLowerCase()))) {
        return res
            .status(400)
            .json(response("1", `The user profile ${user_right_title || user_right_id} provided by the property user_right_title or user_right_id does not match the following profiles: admin, user, supervisor`, "0", "linkUserAndUserRight"));
    }
    const _user = yield User_1.default.findOne({ where: { secondaryId: user_id } });
    if (!_user)
        return res
            .status(404)
            .json(response("1", `User ${user_id} not exist`, "0", "linkUserAndUserRight"));
    const userData = {
        profile: user_right_title || user_right_id,
        email: _user.email
    };
    let user = yield UpdateUserService_1.default({
        userData,
        userId: _user.id,
        ignoreThrow: true
    });
    if (user === null || user === void 0 ? void 0 : user.error) {
        return res
            .status(user === null || user === void 0 ? void 0 : user.status)
            .json(response("0", `${user === null || user === void 0 ? void 0 : user.msg}`, "0", "linkUserAndUserRight"));
    }
    yield logoutUser(_user.id);
    return res
        .status(200)
        .json(response("1", `User ${user_id} associated with ${user_right_title || user_right_id} profile`, "1", "linkUserAndUserRight"));
});
exports.linkUserAndUserRight = linkUserAndUserRight;
const checkUserRight = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
    const { user_id, user_right_id, user_right_title } = req.body;
    const invalid = invalidProperties(req.body, ["user_id", "user_right_id"]);
    if (invalid) {
        return res
            .status(400)
            .json(response("1", `${invalid}`, "0", "checkUserRight"));
    }
    if ((user_right_id &&
        !["admin", "user", "supervisor"].includes(user_right_id === null || user_right_id === void 0 ? void 0 : user_right_id.trim().toLocaleLowerCase())) ||
        (user_right_title &&
            !["admin", "user", "supervisor"].includes(user_right_title === null || user_right_title === void 0 ? void 0 : user_right_title.trim().toLocaleLowerCase()))) {
        return res
            .status(400)
            .json(response("1", `The user profile ${user_right_title || user_right_id} provided by the property user_right_title or user_right_id does not match the following profiles: admin, user, supervisor`, "0", "checkUserRight"));
    }
    const _user = yield User_1.default.findOne({
        where: {
            secondaryId: user_id
        }
    });
    if (!_user)
        return res
            .status(404)
            .json(response("1", `User ${user_id} not exist`, "0", "checkUserRight"));
    if ((user_right_id && _user.profile != user_right_id) ||
        (user_right_title && _user.profile != user_right_title)) {
        return res
            .status(403)
            .json(response("1", `User ${user_id} does not have this profile`, "0", "checkUserRight"));
    }
    return res
        .status(200)
        .json(response("1", `User ${user_id} has ${user_right_title || user_right_id} profile`, "1", "checkUserRight"));
});
exports.checkUserRight = checkUserRight;
function logoutUser(userId) {
    return __awaiter(this, void 0, void 0, function* () {
        yield WhoIsOnlineMonitor_1.stopWhoIsOnlineMonitor();
        let onlineTime = {
            userId: `${userId}`,
            status: "logout..."
        };
        const io = socket_1.getIO();
        io.emit("onlineStatus", {
            action: "logout",
            userOnlineTime: onlineTime
        });
        yield WhoIsOnlineMonitor_1.startWhoIsOnlineMonitor();
    });
}
function response(code, msg, obj, type) {
    let payload = { return_code: code, return_msg: msg };
    switch (type) {
        case "createUser":
            return Object.assign(Object.assign({}, payload), { user_created: obj });
        case "deleteUser":
            return Object.assign(Object.assign({}, payload), { user_removed: obj });
        case "listAllUsers":
            return Object.assign(Object.assign({}, payload), { user_list: obj });
        case "checkUser":
            return Object.assign(Object.assign({}, payload), { user_exists: obj });
        case "updateUser":
            return Object.assign(Object.assign({}, payload), { user_updated: obj });
        case "resetPassword":
            return Object.assign(Object.assign({}, payload), { password_set: obj });
        case "linkUserAndUserRight":
            return Object.assign(Object.assign({}, payload), { user_right_linked: obj });
        case "checkUserRight":
            return Object.assign(Object.assign({}, payload), { user_right_exists: obj });
        default:
            return payload;
    }
}
function invalidProperties(body, pros) {
    for (const field of pros) {
        console.log("body[field]: ", body[field], " field: ", field);
        if (!body[field]) {
            return `${field} is required`;
        }
    }
    return false;
}
