var express = require('express');
var router = express.Router();
const { body, validationResult } = require('express-validator');
const adminController = require('../controllers/adminController');
const employeeController = require('../controllers/employeeController');
const authentification = require('../middlewares/authentification');
const isSuperAdmin = require('../middlewares/isSuperAdmin');
const redirectHome = require('../middlewares/redirectHome');
const db = require('../models');
const bcrypt = require('bcrypt');
const { Op } = require('sequelize');

router.get('/signup', async ( req, res ) => {
    let errors = null;
    let admins = await db.admin.findAll({
        where: { role: 'Admin'}
    });
    res.render('pages/log/signup', { admins ,errors, req })
})

router.post('/signup', [
    // body('matriculeEmployee').notEmpty().withMessage('Le matricule est requis'),
    body('firstName').notEmpty().withMessage('Le nom est requis'),
    body('lastName').notEmpty().withMessage('Le prénom est requis'),
    body('email').isEmail().withMessage('L\'email n\'est pas valide'),    
    // body('password')
    //     .notEmpty().withMessage('Le mot de passe est requis')
    //     .isLength({ min: 6 }).withMessage('Le mot de passe doit contenir au moins 6 caractères'),
    // body('confirmPassword')
    //     .custom((value, { req }) => {
    //     if (value !== req.body.password) {
    //         throw new Error('Les mots de passe ne correspondent pas');
    //     }
    //     return true;
    // })
    ],
    adminController.signupAdmin
)

//  PREND PAR ID
router.get('/:id(\\d+)', authentification,async (req, res) => {
    let errors = null;
    let admin = await db.admin.findOne({ where: { id: req.params.id } });
    let leaders = await db.admin.findAll({
        where: { role: 'Admin'}
    });
    res.render('pages/log/signup.edit.ejs', { leaders ,admin, errors, req })
});

//  MISE A JOUR
router.post('/update', 
    authentification,
    [
    body('firstName').notEmpty().withMessage('Le nom est requis'),
    body('lastName').notEmpty().withMessage('Le prénom est requis'),
    body('email').isEmail().withMessage('L\'email n\'est pas valide'),    
    ],    
    adminController.update
);

//  MISE A JOUR MDP SUPER ADMIN
router.get('/super-reset', authentification,async (req, res) => {
    let errors = null;
    let token = null;
    //  Formulaire pour le nouveau mots de passe
    res.render('pages/log/reset_mdp', { token, req, errors})
});

router.post('/super-reset', authentification,
    [body('newPassword')
        .notEmpty().withMessage('Le mot de passe est requis')
        .isLength({ min: 6 }).withMessage('Le mot de passe doit contenir au moins 6 caractères'),
    body('confirmPassword')
        .custom((value, { req }) => {
        if (value !== req.body.newPassword) {
            throw new Error('Les mots de passe ne correspondent pas');
        }
        return true;
    })],
    async (req, res) => {
    
        const errors = validationResult(req);

        //  Erreur non vide
        if (!errors.isEmpty()) {
            console.log(errors);
            console.log(req.body.newPassword+''+req.body.confirmPassword);
            let token = '';
            return res.render('pages/log/reset_mdp', { errors: errors.array(), req,  token})
        }           
        console.log(req.session.admin)
        //  Trouver l'administrateur
        let admin = await db.admin.findOne({
            where: { id: req.session.admin.id }
        });
        //  Si l'administrateur est dans la BD
        if(admin) {
            let newPassword = req.body.newPassword;
            //  Générer un sel pour le hachage
            const saltRounds = Number(process.env.SALTROUNDS);
            const salt = bcrypt.genSaltSync(saltRounds);
    
            // Crypter le mot de passe
            newPassword = bcrypt.hashSync(
                    newPassword,
                    salt
                );
    
            //  Modifier le mot de passe
            await admin.update({
                password: newPassword
            });                        
            res.redirect(`/admin/${admin.id}`)
        }                                
});

router.get('/signin', redirectHome, async (req, res) => {
    let errors = null;
    res.render('pages/log/signin', { errors, req })
});

router.post('/signin', redirectHome,
    adminController.signinAdmin
)

router.get('/logout',
    authentification,
    adminController.logoutAdmin
)

//  Page pour le mail
router.get('/reset-password', (req, res) => {
    let errors = null;
    let message;
    res.render('pages/log/reset_mdp_mail', {errors: errors, message, req })
});

//  Envoyer lien pour modifier le mdp dans le mail entré
router.post('/reset-password', redirectHome, adminController.resetPassWord);

//  Quand le vrai utilisateur clique sur le lien dans le mail
router.get('/reset-password/:token', async (req, res) => {
    const token = req.params.token;
    let result = await db.token.findOne({
        where: { authToken : token }
    });
    if(result) {
        let errors = null;
        //  Formulaire pour le nouveau mots de passe
        res.render('pages/log/reset_mdp', { token, req, errors})
    }    
    else {
        res.status(500).json({ message: "Token invalid" });
    }
});

//  Quand le formulaire de nouveau mdp est validé
router.post('/reset-password/:token',[
    body('newPassword')
        .notEmpty().withMessage('Le mot de passe est requis')
        .isLength({ min: 6 }).withMessage('Le mot de passe doit contenir au moins 6 caractères'),
    body('confirmPassword')
        .custom((value, { req }) => {
        if (value !== req.body.newPassword) {
            throw new Error('Les mots de passe ne correspondent pas');
        }
        return true;
        })],
    async (req, res) => {
        const token = req.params.token;
        const errors = validationResult(req);

        //  Erreur non vide
        if (!errors.isEmpty()) {
            console.log(errors);
            console.log(req.body.newPassword+''+req.body.confirmPassword);
            res.render('pages/log/reset_mdp', { errors: errors.array(), req,  token})
        }
        else {
            //  Vérifier le token est valid
            let result = await db.token.findOne({
                where: { authToken: token }
            })
            if(result) {
                //  Trouver l'administrateur
                let admin = await db.admin.findOne({
                    where: { id: result.AdmnistratorId }
                });
                //  Si l'administrateur est dans la BD
                if(admin) {
                    let newPassword = req.body.newPassword;
                    //  Générer un sel pour le hachage
                    const saltRounds = Number(process.env.SALTROUNDS);
                    const salt = bcrypt.genSaltSync(saltRounds);
            
                    // Crypter le mot de passe
                    newPassword = bcrypt.hashSync(
                            newPassword,
                            salt
                        );
            
                    //  Modifier le mot de passe
                    await admin.update({
                        password: newPassword
                    });
                    //  Supprimer le token
                    await result.destroy();
                    return res.redirect('/');
                }
            }
            // Erreur: token invalide
            else {
                res.status(500).json({ message: "Token invalid" });
            }        
        }
    });

router.get('/', authentification, async (req, res) => {
    let admins = await db.admin.findAll();
    res.render('pages/admin/liste.admin.ejs', { req, admins })
})

router.get('/canApplicant/:idAdmin(\\d+)', authentification, async (req, res) => {
    let idAdmin = req.params.idAdmin;    
    if(!idAdmin) {
        return res.redirect('/admin');
    }
    let admin = await db.admin.findByPk(idAdmin);
    let employees = await employeeController.listCanApplicant(idAdmin);
    let employeesNotApplicant = await employeeController.listCanNotApplicant(idAdmin);
    res.render('pages/admin/liste.canApplicant.ejs', { req, employees, employeesNotApplicant, admin });
});

router.get('/canApplicant/:idAdmin(\\d+)/delete/:idEmployee(\\d+)', authentification, async (req, res) => {
    let adminId = req.params.idAdmin;    
    let employeeId = req.params.idEmployee;
    if(!adminId || !employeeId) {
        return res.redirect('/admin');
    }

    let admin = await db.admin.findByPk(adminId);
    let employee = await db.employee.findByPk(employeeId);
    if(!admin || !employee) {
        return res.redirect('/admin');
    }

    let rslt = await db.adminEmployee.findOne({
        where: {
            [Op.and]: [
                { AdmnistratorId: adminId },
                { employeeId: employeeId }
            ]
        }
    });

    if(rslt) {
        await rslt.update({ isApplicant: false });
    }
    else {        
        await db.adminEmployee.create({ isApplicant: false, AdmnistratorId: adminId, employeeId: employeeId });
    }
    res.redirect(`/admin/canApplicant/${adminId}`)
});

router.post('/canApplicant', authentification, async (req, res) => {
    let employeeId = req.body.employeeId;
    let adminId = req.body.adminId;

    // verifications
    let r1 = await db.employee.findByPk(employeeId);
    let r2 = await db.admin.findByPk(adminId);
    if(!r1 || !r2) {
        return res.redirect('/admin');
    }

    let rslt = await db.adminEmployee.findOne({
        where: {
            [Op.and]: [
                { AdmnistratorId: adminId },
                { employeeId: employeeId }
            ]
        }
    });

    if(rslt) {
        await rslt.update({ isApplicant: true });
    }
    else {        
        await db.adminEmployee.create({ isApplicant: true, AdmnistratorId: adminId, employeeId: employeeId });
    }

    res.redirect(`/admin/canApplicant/${adminId}`);
})

router.get('/canValidate/:idAdmin(\\d+)', authentification, async (req, res) => {
    let idAdmin = req.params.idAdmin;    
    if(!idAdmin) {
        return res.redirect('/admin');
    }
    let admin = await db.admin.findByPk(idAdmin);
    let employees = await employeeController.listCanValidate(idAdmin);
    let employeesNotValidate = await employeeController.listCanNotValidate(idAdmin);
    res.render('pages/admin/liste.canValidate.ejs', { req, employees, employeesNotValidate, admin });
});

router.get('/canValidate/:idAdmin(\\d+)/delete/:idEmployee(\\d+)', authentification, async (req, res) => {
    let adminId = req.params.idAdmin;    
    let employeeId = req.params.idEmployee;
    if(!adminId || !employeeId) {
        return res.redirect('/admin');
    }

    let admin = await db.admin.findByPk(adminId);
    let employee = await db.employee.findByPk(employeeId);
    if(!admin || !employee) {
        return res.redirect('/admin');
    }

    let rslt = await db.adminEmployee.findOne({
        where: {
            [Op.and]: [
                { AdmnistratorId: adminId },
                { employeeId: employeeId }
            ]
        }
    });

    if(rslt) {
        await rslt.update({ isValidator: false });
    }
    else {        
        await db.adminEmployee.create({ isValidator: false, AdmnistratorId: adminId, employeeId: employeeId });
    }
    res.redirect(`/admin/canValidate/${adminId}`)
});

router.post('/canValidate', authentification, async (req, res) => {
    let employeeId = req.body.employeeId;
    let adminId = req.body.adminId;

    // verifications
    let r1 = await db.employee.findByPk(employeeId);
    let r2 = await db.admin.findByPk(adminId);
    if(!r1 || !r2) {
        return res.redirect('/admin');
    }

    // SI l'employee est peut etre demander par l'admin ou inverse
    let rslt = await db.adminEmployee.findOne({
        where: {
            [Op.and]: [
                { AdmnistratorId: adminId },
                { employeeId: employeeId }
            ]
        }
    });

    if(rslt) {
        console.log(rslt)
        await rslt.update({isValidator: true});
    }
    else {
        await db.adminEmployee.create({ isValidator: true, AdmnistratorId: adminId, employeeId: employeeId });
    }

    res.redirect(`/admin/canValidate/${adminId}`);
})

module.exports = router;