"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.editCarimbo = exports.editAssinatura = exports.togglePermission = exports.changeStatus = exports.changeFuncao = exports.deleteUser = exports.getAdmin = exports.getAdmins = exports.registerUserAdmin = void 0;
const express_validator_1 = require("express-validator");
const upload_1 = require("../../middleware/upload");
const postmark_1 = __importDefault(require("../../services/postmark"));
const aws_1 = require("../../services/aws");
const main_1 = require("../../util/main");
const pagination_1 = require("../../util/pagination");
const verification_code_1 = __importDefault(require("../../util/verification-code"));
const prisma_1 = require("../../database/prisma");
const prisma_2 = require("../../generated/prisma");
// Metodo para registar Admin
const registerUserAdmin = async (req, res, next) => {
    var _a;
    try {
        let { nome, email, tel1, tel2, genero, provincia, municipio, bairro, perfil, rua, numeroBI, tipoIdentificacao, permissions, 
        // Dados do secretario
        userId, } = req.body;
        const errors = (0, express_validator_1.validationResult)(req);
        let espacoDesportivo;
        numeroBI = numeroBI.toUpperCase();
        let admin;
        const foto = req.file;
        if (!Object.values(prisma_2.UserRole).includes(perfil)) {
            const error = new Error(`Perfil inválido!`);
            error.statusCode = 422;
            throw error;
        }
        if (Boolean(userId)) {
            admin = await prisma_1.prisma.user.findUnique({ where: { id: Number(userId) } });
            if (!admin) {
                const error = new Error(`Admin não encontrado!`);
                error.statusCode = 422;
                throw error;
            }
        }
        const foundEmail = await prisma_1.prisma.dadosPessoais.findFirst({ where: { email } });
        if (foundEmail) {
            const error = new Error(`O email '${email}' já está sendo usado!`);
            error.statusCode = 422;
            throw error;
        }
        let dadosPessoais = await prisma_1.prisma.dadosPessoais.create({
            data: {
                nome,
                numeroBI,
                email,
                provincia,
                municipio,
                bairro,
                genero,
                perfil,
                isAdmin: true,
                tipoIdentificacao: tipoIdentificacao || undefined,
                rua: rua || undefined,
                tel1: tel1 || undefined,
                tel2: tel2 || undefined,
            },
        });
        if (Boolean(tipoIdentificacao)) {
            dadosPessoais.tipoIdentificacao = tipoIdentificacao;
        }
        if (Boolean(numeroBI)) {
            const filtro = {
                numeroBI: numeroBI.toUpperCase(),
                isAdmin: true,
                espacoDesportivo,
            };
            if (Boolean(tipoIdentificacao)) {
                filtro.tipoIdentificacao = tipoIdentificacao;
            }
            const foundBI = await prisma_1.prisma.dadosPessoais.findFirst({ where: filtro });
            if (foundBI) {
                const error = new Error(`O número do BI '${numeroBI.toUpperCase()}' já está sendo usado!`);
                error.statusCode = 422;
                throw error;
            }
            dadosPessoais.numeroBI = numeroBI;
        }
        if (Boolean(rua)) {
            dadosPessoais.rua = rua;
        }
        if (Boolean(tel1)) {
            const foundTel1 = await prisma_1.prisma.dadosPessoais.findFirst({
                where: {
                    tel1: tel1,
                    isAdmin: true,
                },
            });
            if (foundTel1) {
                const error = new Error(`O telefone '${tel1}' já está sendo usado!`);
                error.statusCode = 422;
                throw error;
            }
            dadosPessoais.tel1 = tel1;
        }
        if (Boolean(tel2)) {
            dadosPessoais.tel2 = tel2;
        }
        const codigoVerificao = (0, verification_code_1.default)(6);
        const { password, hashPassword } = await (0, main_1.generatePassword)();
        let user = await prisma_1.prisma.user.create({
            data: {
                email: dadosPessoais.email,
                funcao: perfil,
                password: hashPassword,
                codigoVerificao,
                dadosPessoaisId: dadosPessoais.id,
                isAdmin: true,
                roles: perfil,
                emailVerified: true,
                editPassword: true,
                permissions: permissions || undefined,
            },
            include: { dadosPessoais: true },
        });
        // HistoricoActividade
        await (0, main_1.createHistoricoActividade)(`Cadastrou admin ${(_a = user === null || user === void 0 ? void 0 : user.dadosPessoais) === null || _a === void 0 ? void 0 : _a.nome}`, 'User', user.id, admin);
        await postmark_1.default.sendEmail({
            To: dadosPessoais.email,
            From: process.env.SENDER_EMAIL,
            Subject: `Conta Admin — Infrasat`,
            HtmlBody: `
      <h2>Bem-vindo ao Infrasat</h2>

        <p>
          Saudações ${dadosPessoais.nome},
        </p>

        <p>
          Esperamos que esteja bem.<br/>
          A sua conta admin foi criada com sucesso.
        </p>

        <p>A sua conta encontra-se activa e pronta para utilização. Seguem as credenciais de acesso:</p>

        <p><b>Email:</b> ${dadosPessoais.email}</p>

        <p><b>Senha:</b> ${password}</p>

        <p>
          A senha foi gerada automaticamente altere no primeiro acesso.
        </p>

        <p>
          Se precisar de qualquer apoio, estaremos disponíveis para ajudar.
        </p>
        
        <br/>
        <p>
          Com os melhores cumprimentos,<br/>
          <b>Equipa Infrasat</b> <br />
          <table cellpadding="0" cellspacing="0" style="text-align: center; font-family: Arial, sans-serif; font-size: 14px; color: #555;">
            <tr>
              <td>
                <a href="https://infrasat.com" style="color: #007bff; text-decoration: none; margin-right: 15px;">www.infrasat.com</a>
                |
                <a href="mailto:infrasat.app@gmail.com" style="color: #007bff; text-decoration: none; margin: 0 15px;">infrasat.app@gmail.com</a>
                |
                <a href="http://facebook.com/infrasat" style="color: #007bff; text-decoration: none; margin-left: 15px;">Facebook</a>
              </td>
            </tr>
          </table>
        </p>
        `,
            MessageStream: 'outbound',
        });
        if (foto) {
            foto.filename = (0, upload_1.generateFileName)(foto);
            dadosPessoais.fotoURL = foto.filename;
            await (0, aws_1.uploadFile)(foto);
            await prisma_1.prisma.dadosPessoais.update({
                where: { id: dadosPessoais.id },
                data: { fotoURL: foto.filename },
            });
        }
        res.status(201).json({
            msg: 'Sucesso',
            user,
        });
    }
    catch (err) {
        next(err);
    }
};
exports.registerUserAdmin = registerUserAdmin;
const getAdmins = async (req, res, next) => {
    try {
        const { status, cnp, funcao, seccao, espacoDesportivoId } = req.query;
        const page = (0, pagination_1.getPage)(req.query.page);
        let paramPerPage = req.query.perPage;
        let perPage = 50;
        if (paramPerPage) {
            perPage = +paramPerPage;
        }
        const filterObject = {
            isAdmin: true,
            funcao: { not: 'CNP' },
        };
        if (Boolean(status)) {
            filterObject.status = status;
        }
        if (Boolean(cnp)) {
            filterObject.funcao = 'CNP';
        }
        if (Boolean(funcao)) {
            filterObject.funcao = funcao;
        }
        if (Boolean(seccao)) {
            filterObject.seccao = seccao;
        }
        if (Boolean(espacoDesportivoId)) {
            filterObject.espacoDesportivo = espacoDesportivoId;
        }
        const total = await prisma_1.prisma.user.count({ where: filterObject });
        const userAdmins = await prisma_1.prisma.user.findMany({
            where: filterObject,
            take: perPage,
            skip: (0, pagination_1.skip)(page, perPage),
            orderBy: { createdAt: 'desc' },
            include: { dadosPessoais: true },
        });
        for (let user of userAdmins) {
            let dadosPessoais = user.dadosPessoais;
            if (dadosPessoais) {
                dadosPessoais.fotoURL = await (0, aws_1.getURL)(dadosPessoais.fotoURL);
            }
            if (user.assinatura) {
                user.assinatura = await (0, aws_1.getURL)(user.assinatura);
            }
            if (user.carimbo) {
                user.carimbo = await (0, aws_1.getURL)(user.carimbo);
            }
        }
        res.status(200).json({
            msg: 'Sucesso',
            Admins: userAdmins,
            ...(0, pagination_1.paginationResult)(total, page, perPage),
        });
    }
    catch (err) {
        next(err);
    }
};
exports.getAdmins = getAdmins;
// Funcao que busca um Admin pelo Id
const getAdmin = async (req, res, next) => {
    try {
        const { id } = req.params;
        const admin = await prisma_1.prisma.user.findFirst({ where: { id: Number(id), isAdmin: true }, include: { dadosPessoais: true } });
        if (!admin) {
            const error = new Error('Admin não encontrado!');
            error.statusCode = 422;
            throw error;
        }
        let dadosPessoais = admin.dadosPessoais;
        if (dadosPessoais) {
            dadosPessoais.fotoURL = await (0, aws_1.getURL)(dadosPessoais.fotoURL);
        }
        res.status(200).json({ msg: 'Sucesso', admin });
    }
    catch (err) {
        next(err);
    }
};
exports.getAdmin = getAdmin;
const deleteUser = async (req, res, next) => {
    try {
        const { id, userId } = req.body;
        const errors = (0, express_validator_1.validationResult)(req);
        if (!errors.isEmpty()) {
            const error = new Error(errors.array()[0].msg);
            error.statusCode = 422;
            throw error;
        }
        const admin = await prisma_1.prisma.user.findFirst({ where: { id: Number(userId), isAdmin: true } });
        if (!admin) {
            const error = new Error('Admin não encontrado!');
            error.statusCode = 422;
            throw error;
        }
        const user = await prisma_1.prisma.user.findUnique({ where: { id: Number(id) } });
        if (!user) {
            const error = new Error(`Utilizador não encontrado!`);
            error.statusCode = 422;
            throw error;
        }
        const dadosPessoais = (user === null || user === void 0 ? void 0 : user.dadosPessoaisId)
            ? await prisma_1.prisma.dadosPessoais.findUnique({ where: { id: user.dadosPessoaisId } })
            : null;
        if (dadosPessoais &&
            dadosPessoais.fotoURL &&
            dadosPessoais.perfil === user.funcao) {
            await (0, aws_1.deleteFile)(dadosPessoais.fotoURL);
            await prisma_1.prisma.dadosPessoais.delete({ where: { id: dadosPessoais.id } });
        }
        await prisma_1.prisma.user.delete({ where: { id: user.id } });
        await (0, main_1.createHistoricoActividade)(`Deletou utilizador`, 'User', user.id, admin);
        res.status(204).json({ msg: 'Deletado com sucesso!' });
    }
    catch (error) {
        next(error);
    }
};
exports.deleteUser = deleteUser;
// Metodo para editar a funcao do Admin
const changeFuncao = async (req, res, next) => {
    try {
        const { funcao, userId, adminId } = req.body;
        const errors = (0, express_validator_1.validationResult)(req);
        if (!errors.isEmpty()) {
            const error = new Error(errors.array()[0].msg);
            error.statusCode = 422;
            throw error;
        }
        // Admin a realizar a operacao
        const admin = await prisma_1.prisma.user.findFirst({ where: { id: Number(userId), isAdmin: true }, include: { dadosPessoais: true } });
        if (!admin) {
            const error = new Error(`Admin não encontrado!`);
            error.statusCode = 422;
            throw error;
        }
        // Admin a ser alterado a funcao
        const userAdmin = await prisma_1.prisma.user.findFirst({ where: { id: Number(adminId), isAdmin: true }, include: { dadosPessoais: true } });
        if (!userAdmin) {
            const error = new Error(`User admin não encontrado!`);
            error.statusCode = 422;
            throw error;
        }
        const dadosPessoais = userAdmin.dadosPessoaisId
            ? await prisma_1.prisma.dadosPessoais.findUnique({ where: { id: userAdmin.dadosPessoaisId } })
            : null;
        if (!dadosPessoais) {
            const error = new Error(`Dados pessoais não encontrado!`);
            error.statusCode = 422;
            throw error;
        }
        await prisma_1.prisma.dadosPessoais.update({ where: { id: dadosPessoais.id }, data: { perfil: funcao } });
        const updatedUserAdmin = await prisma_1.prisma.user.update({ where: { id: userAdmin.id }, data: { funcao } });
        await (0, main_1.createHistoricoActividade)('Alterou funcao de admin', 'Admin', updatedUserAdmin.id, admin);
        res.status(201).json({
            msg: 'Sucesso',
            user: updatedUserAdmin,
        });
    }
    catch (err) {
        next(err);
    }
};
exports.changeFuncao = changeFuncao;
const changeStatus = async (req, res, next) => {
    try {
        const { status, userId, adminId } = req.body;
        const errors = (0, express_validator_1.validationResult)(req);
        if (!errors.isEmpty()) {
            const error = new Error(errors.array()[0].msg);
            error.statusCode = 422;
            throw error;
        }
        // Admin a realizar a operacao
        const admin = await prisma_1.prisma.user.findFirst({ where: { id: Number(userId), isAdmin: true }, include: { dadosPessoais: true } });
        if (!admin) {
            const error = new Error(`Admin não encontrado!`);
            error.statusCode = 422;
            throw error;
        }
        // Admin a ser alterado a funcao
        const userAdmin = await prisma_1.prisma.user.findFirst({ where: { id: Number(adminId), isAdmin: true }, include: { dadosPessoais: true } });
        if (!userAdmin) {
            const error = new Error(`User admin não encontrado!`);
            error.statusCode = 422;
            throw error;
        }
        // Altera a funcao no user
        const updatedUserAdmin = await prisma_1.prisma.user.update({ where: { id: userAdmin.id }, data: { status } });
        await (0, main_1.createHistoricoActividade)(`Alterou o estado do admin ${status}`, 'Admin', userAdmin.id, admin);
        res.status(201).json({
            msg: 'Sucesso',
            user: userAdmin,
        });
    }
    catch (err) {
        next(err);
    }
};
exports.changeStatus = changeStatus;
const togglePermission = async (req, res, next) => {
    try {
        const { permission, userId, observacao, adminId } = req.body;
        const errors = (0, express_validator_1.validationResult)(req);
        let updatedUser;
        if (!errors.isEmpty()) {
            const error = new Error(errors.array()[0].msg);
            error.statusCode = 422;
            throw error;
        }
        // Admin a realizar a operacao
        const admin = await prisma_1.prisma.user.findFirst({ where: { id: Number(userId), isAdmin: true }, include: { dadosPessoais: true } });
        if (!admin) {
            const error = new Error(`Admin não encontrado!`);
            error.statusCode = 422;
            throw error;
        }
        // Admin a ser alterado a funcao
        const userAdmin = await prisma_1.prisma.user.findFirst({ where: { id: Number(adminId), isAdmin: true }, include: { dadosPessoais: true } });
        if (!userAdmin) {
            const error = new Error(`User não encontrado!`);
            error.statusCode = 422;
            throw error;
        }
        const permissions = userAdmin.permissions;
        if (permissions.includes(permission)) {
            userAdmin.permissions = permissions.filter((p) => p !== permission);
            updatedUser = await prisma_1.prisma.user.update({
                where: { id: userAdmin.id },
                data: { permissions: userAdmin.permissions },
            });
            await (0, main_1.createHistoricoActividade)(`Removeu permissão '${permission}'`, 'Admin', userAdmin.id, admin, observacao);
        }
        else {
            permissions.push(permission);
            updatedUser = await prisma_1.prisma.user.update({
                where: { id: userAdmin.id },
                data: { permissions },
            });
            await (0, main_1.createHistoricoActividade)(`Atribuiu permissão '${permission}'`, 'Admin', userAdmin.id, admin, observacao);
        }
        res.status(201).json({
            msg: 'Sucesso',
            user: updatedUser,
            permissions: updatedUser.permissions,
        });
    }
    catch (err) {
        next(err);
    }
};
exports.togglePermission = togglePermission;
//Função para adicionar assinatura de usuario
const editAssinatura = async (req, res, next) => {
    try {
        const { dadosPessoaisId, userId } = req.body;
        const assinatura = req.file;
        const errors = (0, express_validator_1.validationResult)(req);
        let admin;
        if (!errors.isEmpty()) {
            const error = new Error(errors.array()[0].msg);
            error.statusCode = 422;
            throw error;
        }
        if (!assinatura) {
            const error = new Error('Por favor fornceça uma assinatura');
            error.statusCode = 422;
            throw error;
        }
        if (Boolean(userId)) {
            admin = await prisma_1.prisma.user.findFirst({ where: { id: Number(userId) } });
            if (!admin) {
                const error = new Error('Admin não encontrados!');
                error.statusCode = 422;
                throw error;
            }
            // Depois renomeia e faz o upload
            assinatura.filename = (0, upload_1.generateFileName)(assinatura);
            await (0, aws_1.uploadFile)(assinatura);
            admin.assinatura = assinatura.filename;
            await prisma_1.prisma.user.update({ where: { id: admin.id }, data: { assinatura: admin.assinatura } });
        }
        // let action = 'Editou Assinatura';
        // if (admin) {
        //   await createHistoricoActividade(
        //     action,
        //     'DadosPessoais',
        //     dadosPessoaisId,
        //     admin,
        //   );
        // }
        res.status(201).json({
            msg: 'Editado com sucesso!',
        });
    }
    catch (error) {
        next(error);
    }
};
exports.editAssinatura = editAssinatura;
//Função para adicionar carimbo do sitema a um usuario
const editCarimbo = async (req, res, next) => {
    try {
        const { dadosPessoaisId, userId } = req.body;
        const carimbo = req.file;
        const errors = (0, express_validator_1.validationResult)(req);
        let admin;
        if (!errors.isEmpty()) {
            const error = new Error(errors.array()[0].msg);
            error.statusCode = 422;
            throw error;
        }
        if (!carimbo) {
            const error = new Error('Por favor fornceça um carimbo');
            error.statusCode = 422;
            throw error;
        }
        if (Boolean(userId)) {
            admin = await prisma_1.prisma.user.findFirst({ where: { id: Number(userId) } });
            if (!admin) {
                const error = new Error('Admin não encontrados!');
                error.statusCode = 422;
                throw error;
            }
            // Depois renomeia e faz o upload
            carimbo.filename = (0, upload_1.generateFileName)(carimbo);
            await (0, aws_1.uploadFile)(carimbo);
            admin.carimbo = carimbo.filename;
            await prisma_1.prisma.user.update({ where: { id: admin.id }, data: { carimbo: admin.carimbo } });
        }
        // let action = 'Editou Assinatura';
        // if (admin) {
        //   await createHistoricoActividade(
        //     action,
        //     'DadosPessoais',
        //     dadosPessoaisId,
        //     admin,
        //   );
        // }
        res.status(201).json({
            msg: 'Editado com sucesso!',
        });
    }
    catch (error) {
        next(error);
    }
};
exports.editCarimbo = editCarimbo;
