const moment = require('moment');
const DB = require('../models/index');
const functionController = require('./functionController');
const { Op } = require('sequelize');

const getPermissionOnYear = async (employeeId, currentDate) => {
    const YEAR = moment(currentDate).year();

    //  Verify employee
    let employee = await DB.employee.findByPk(employeeId);
    if(!employee) {
        return 0;
    }

    let nbrPermission = 0;
    // All permission of employee
    let permissions = await DB.permission.findAll({
        where: {
            employeeId: employeeId,
        }
    });

    //  Permissing of YEAR
    permissions.forEach(permission => {
        let year = moment(permission.startDate).year();
        if(year == YEAR) {
            nbrPermission += permission.nbrDays;
        }
    });
    return nbrPermission;
}

const requestPermission = async (req, res) => {
    let { demandeur, event, start, end, id, matricule, name, interimId, direction, interimaire } = req.body;    

    //  VERIFIER QUE CE SONT DES FUTURES DATES
    let n = nbrDaysBetweenDates(moment(), start);

    // Date de debut plus tot qu'aujourdhui et moin d'une semaine
    //  Seul le super admin peut demander un conge avec la date de depart est moins d'une semaine  
    if( req.session && req.session.admin && req.session.admin.role !== 'Super admin') {
        if(n <= 0 ) {    
            let msg = "Date de début non valide.";
            return returnRequestPermission(msg, req, res)
        }
        if( n < 7) {
            let msg = "Date de début non valide.";
            return returnRequestPermission(msg, req, res)
        }
    }

    //  DATE LOGIQUE start <= end
    let nbrDays = nbrDaysBetweenDates(moment(start), moment(end));
    //  Si le start est plus tard que end
    if( nbrDays < 0 ) {
        tmp = start;
        start = end;
        end = tmp;
    }

    //  VERIFIER QUE C'EST UN VRAI EMPLOYEE
    //  VERIFIER QUE C'EST UN VRAI EMPLOYEE
  if(id !== '') {    
    let employee = await DB.employee.findOne({ where: { id: id}});
    if(!employee) {      
      let msg = "Utilisateur introuvable.";
      return returnRequestPermission(msg, req, res);      
    }    

    //  ROLE DE EMPLOYEE S'IL A UN ROLE
    let roleEmployee = await DB.admin.findOne({ where: { matriculeEmployee: employee.matricule }});
    if(!roleEmployee) {      
      roleEmployee = '';      
    }

    // TROUVER LE DEMANDEUR
    let applicant = await DB.admin.findOne({ where: { id: demandeur }});
    if(!applicant) {      
      let msg = "Demandeur introuvable.";
      return returnRequestVacation(msg, req, res);
    }

    //  ENREGISTRER LA PERMISSION OU LA DEMANDE    
    let permission = await DB.permission.create({
      nbrDays: nbrDaysBetweenDates(start, end),
      startDate: moment(start),
      endDate: moment(end),
      AdmnistratorId: null,
      interimId: interimId,
      event: event,
      applicantId: applicant.id,
      employeeId: id
    });

    //  PIECE JUSTIFICATIF
    if(req.file) {        
        const { fieldname, filename, path, mimetype } = req.file;        
        let r = await DB.permissionJustificative.create({
            filename,
            path,
            mimetype,
            permissionId: permission.id
        });        
    }
    
  
    //  ENVOYER LE MAIL VERS LEUR SUPERIEUR DE L'EMPLOYEE
    //  Fonction de l'employee
    let fonction = await functionController.getFunctionEmployee(employee.id);    
    employee.fonction = fonction ? fonction.nameFunction : '';    

    const MAIL = process.env.ENV == 'prod' ? process.env.MAIL : process.env.MAIL_LOCAL;

    //  Validateurs à envoyer le mail de notifications
    let idValidators = await DB.adminEmployee.findAll({ where: {
      [Op.and]: [
        { isValidator: true },
        { employeeId: employee.id }
      ]
    }});

    let allAdmin = [];
    for(let i = 0; i < idValidators.length; i++) {
      let admin = await DB.admin.findOne({ where:{ id: idValidators[i].AdmnistratorId}});
      if(admin) {
        allAdmin.push(admin);
      }
    }    
    var mails = [];
    allAdmin.forEach(function(admin) {
      mails.push(admin.email);
    })    
    console.log(mails)

    for( i = 0; i < mails.length; i++ ) {
      let email = mails[i];      
      if( email !== applicant.email ) {
        const mailOptions = {          
            from: MAIL,
            to: email,
            subject: 'Demande de validation de permission',
            text: 
            `${employee.name_employee} ${employee.last_name_employee}
            matricule:${employee.matricule}
            Fonction: ${employee.fonction}
            Veuillez-vous connecter sur le site ${process.env.SITE}`
        };        
        console.log(email);
        // transporter.sendMail(mailOptions, (error, info) => {
        //     if (error) {
        //         console.error('Erreur lors de l\'envoi de l\'e-mail de réinitialisation de mot de passe :', error);
        //         return res.status(500).json({ message: 'Erreur lors de l\'envoi de l\'e-mail de réinitialisation de mot de passe' });
        //     }
    
        //     console.log('E-mail de réinitialisation de mot de passe envoyé :', info.response);            
        //     return res.redirect('/');
        // });
      }
  
    }
    if(interimaire !== '') {

      let data = {
        poste: employee.fonction,
        direction: req.body.direction,
        holder: employee.name_employee + ' ' + employee.last_name_employee,
        interim: interimaire,
        permissionId: permission.id,
        vacationId: null,
      }
  
      // Passation de service
      try {
          var passFile = await DB.passingFile.create(data);
      }
      catch(err) {
          console.log(err);
          return res.send(err);
      }
  
      //  Tache
      let task = req.body.taches;
      let deliverable = req.body.livrables;
      let reference = req.body.referentiels;
  
      if(task && deliverable && reference) {
            //  S'il y a plusieurs (tableau)            
          if( Array.isArray(task) && Array.isArray(deliverable) && Array.isArray(reference) ) {
              for(let i = 0; i < task.length && i < deliverable.length && i < reference.length; i++) {                    
                  if(task[i] && deliverable[i] && reference[i]) {
                      let rslt = await DB.task.create({
                          description : task[i], 
                          deliverable : deliverable[i],
                          reference : reference[i],
                          passingFileId: passFile.id                
                      });
                  }
              }
          }
          else {                
              let rslt = await DB.task.create({
                  description : task, 
                  deliverable, 
                  reference,
                  passingFileId: passFile.id
              });                
          }
      }
  
      //  Personnel
      let noms = req.body.noms;
      let fonctions = req.body.fonctions;
  
      if(noms && fonctions) {            
          if( Array.isArray(noms) && Array.isArray(fonctions) ) {
              for(let i = 0; i < noms.length && i < fonctions.length ; i++) {
                  if(noms[i] && fonctions[i]) {
                      let rslt = await DB.personnel.create({
                          name_and_last: noms[i],
                          fonction: fonctions[i],
                          passingFileId: passFile.id                
                      });
                  }
              }
          }
          else {                
              let rslt = await DB.personnel.create({
                  name_and_last: noms,
                  fonction: fonctions,
                  passingFileId: passFile.id
              });                
          }
      }
  
      //  Materiels
      let description = req.body.descriptions;
      let quantity = req.body.quantities;
      let state = req.body.etats;      
  
      if(description && quantity && state) {            
          if( Array.isArray(description) && Array.isArray(quantity) && Array.isArray(state)) {
              for(let i = 0; i < description.length && i < quantity.length && i < state.length; i++) {
                  if(description[i] && quantity[i] && state[i]) {
                      let rslt = await DB.material.create({
                          description: description[i],
                          quantity: quantity[i],
                          state: state[i],
                          passingFileId: passFile.id                
                      });
                  }
              }
          }
          else {                
              let rslt = await DB.material.create({
                  description: description,
                  quantity: quantity,
                  state: state,
                  passingFileId: passFile.id
              });                
          }
      }
  
      // Signatures
      let doc_type = req.body.typeDocs;
      let responsability_level = req.body.responsabilites;
  
      if(doc_type && responsability_level) {            
          if( Array.isArray(doc_type) && Array.isArray(responsability_level) ) {
              for(let i = 0; i < doc_type.length && i < responsability_level.length ; i++) {
                  if(doc_type[i] && responsability_level[i]) {
                      let rslt = await DB.signature.create({
                          doc_type: doc_type[i],
                          responsability_level: responsability_level[i],
                          passingFileId: passFile.id                
                      });
                  }
              }
          }
          else {                
              let rslt = await DB.signature.create({
                  doc_type: doc_type,
                  responsability_level: responsability_level,
                  passingFileId: passFile.id                                    
              });                
          }
      }    
    }

    return res.redirect(`/permission/${permission.id}`);
  }
  else {    
    let msg = "Veuillez choisir un employé";
    return returnRequestPermission(msg, req, res);
  }
}

const returnRequestPermission = async (msg, req, res) => {
    //  Id de l'employee 
    const id = req.params.id || null;
    let errors = [{
        msg: msg
    }];
    let employees = [];
    
    //  Pour le simple demande
    if (!id) {    
        //  Trouver tout les employees
        var allEmployee = await DB.employee.findAll();  
        for(let i = 0; i < allEmployee.length; i++) {
            allEmployee[i].interims = [];
            if(allEmployee[i]) {
                let interims = await DB.interim.findAll({ where:{ employeeId: allEmployee[i].id }});
                for(let j = 0; j < interims.length; j++) {
                    let interim = await DB.employee.findOne({ where: { id: interims[j].interimId}});
                    if(interim) {
                        allEmployee[i].interims.push(interim)
                    }
                }
            }       
        }      
        console.log(allEmployee[0].interims)
    }
    //  Pour le demande personnaliser d'un employee
    else {
        var allEmployee = [];
        result = await DB.employee.findOne({ where: { id: id }});
        //  Leur interimaire
        if(result) {
            result.interims = [];
            let interims = await DB.interim.findAll({ where:{ employeeId: result.id }});
            for(let j = 0; j < interims.length; j++) {
                let interim = await DB.employee.findOne({ where: { id: interims[j].interimId}});
                if(interim) {
                    result.interims.push(interim)
                }
            }            
            allEmployee.push(result);
        }
    }
    //  Trouver leurs permission de l'annee
    for( i = 0; i < allEmployee.length; i++ ) {        
        
        let canApplicant = await DB.adminEmployee.findOne({where : {
            [Op.and]: [
                { isApplicant: true },
                { employeeId: allEmployee[i].id },
                { AdmnistratorId: req.session.admin.id }
            ]
        }})
        
        if( canApplicant ) {            
            let employee = allEmployee[i];
            employee.permission = await getPermissionOnYear(1, new moment());
            let fonction = await FunctionController.getFunctionEmployee(employee.id);
            if(fonction) {
                employee.fonction = fonction.nameFunction;
            }
            else {
                employee.fonction = '';
            }            
            employees.push(employee);
        }                
    }                   
    res.render('pages/forms/permission.ejs', { employees, errors, req });
}

const update = async (req, res) => {
    let id = req.params.id || null;
    let { idEmployee, valid, validator = null } = req.body;    

    if( id && idEmployee !== '' ) {                    
        if(validator && valid == 'on' ) {      
            let admin = await DB.admin.findOne({ where: { id: validator }})
            if(admin) {        
                //  permission valider        
                await DB.permission.update(
                    { AdmnistratorId: (valid == 'on') ? admin.id : null },
                    { where: {id: id }}
                );
                
                //  Envoyer mail vers demandeur que le conge est valider
                //  Trouver le demandeur et l'employee  
                let permission = await DB.permission.findByPk(id);
                let applicant = await DB.admin.findOne({ where: {id : permission.applicantId }});
                let employee = await DB.employee.findOne({ where: { id: permission.employeeId }})
                if(applicant) {
                    let email = applicant.email;
                    const MAIL = process.env.ENV == 'prod' ? process.env.MAIL : process.env.MAIL_LOCAL;
                    
                    //  Trouver le validateur
                    let validateur = await DB.admin.findOne({ where: { id: permission.AdmnistratorId }});
                    if(validateur) {                                
                    const mailOptions = {          
                        from: MAIL,
                        to: email,
                        subject: 'Validation de permission',
                        text: 
                        `${employee.name_employee} ${employee.last_name_employee}
                        matricule:${employee.matricule}
                        permission validée par ${validateur.firstName} ${validateur.lastName}
                        Veuillez-vous connecter sur le site ${process.env.SITE} pour voir le détail`          
                    };        
                    console.log(email)
                        // transporter.sendMail(mailOptions, (error, info) => {
                        //     if (error) {
                        //         console.error('Erreur lors de l\'envoi de l\'e-mail de réinitialisation de mot de passe :', error);              
                        //     }          
                        //     console.log('E-mail envoyé :', info.response);                      
                        // });
                    }
                }
            }      
            // return res.redirect('/');
        } 
    }
    else {    
        msg = "Veuillez choisir un employé"    
        return returnRequestPermission(msg, req, res);
    }  
    // res.send('miverina')
    res.redirect(`/`);
}

const nbrDaysBetweenDates = (startDate, endDate = moment() ) => {
    var nbrDays = moment(endDate).diff(moment(startDate), 'days');
    return nbrDays;
}

const waitingPermiss = async (req) => {
    let permissions = await DB.permission.findAll({
        where: { AdmnistratorId: null }
      });
      
    let data = [];
    for( i = 0; i < permissions.length; i++) {      
        let employee = await DB.employee.findOne({ where: { id: permissions[i].employeeId }});
        let canValidate = await DB.adminEmployee.findOne({ where: {
          [Op.and]: [
            { isValidator: true },
            { employeeId: employee.id },
            { AdmnistratorId: req.session.admin.id }
          ]
        }});    
        //  Leur fonction
        if(employee && canValidate) {          
          employee.fonction = await functionController.getFunctionEmployee(employee.id);
          employee.permission = permissions[i];
          //  Trouver le demandeur
          let applicant = await DB.admin.findOne({ where: { id: employee.permission.applicantId }});
          if(applicant) {
            employee.permission.applicant = applicant;
          }          
          data.push(employee);
        }            
    }
      return data;
}

// conge prochain
const nextPermission = async ( req, nowDate ) => {
  let now = nowDate;
  let permissions = await DB.permission.findAll({
    where: {
      [Op.and]: [
        { startDate: { [Op.not]: null }}, // startDate is not null       
        { startDate: { [Op.gt]: now }}, //  startDate > now
        { AdmnistratorId: { [Op.not]: null }},
        { AdmnistratorId: { [Op.gt]: 0 }}, // Valeur > 0
      ]
    }
  });

  let data = [];
  for( let i = 0; i < permissions.length; i++) {
    let nbrDays = nbrDaysBetweenDates( now, permissions[i].startDate );    
    if(nbrDays <= 30 && nbrDays > 0 ) {
      
      let employee = await DB.employee.findOne({ where: { id: permissions[i].employeeId }});
      //  Leur fonction
      if(employee) {        
        employee.fonction = await functionController.getFunctionEmployee(employee.id);
        employee.permission = permissions[i];
        //  Trouver le validateur
        if(employee.permission) {
          var validateur = await DB.admin.findOne({ where: { id: employee.permission.AdmnistratorId }});
          if(validateur) {                    
            employee.permission.validateur = validateur;
          }        
        }        
        
        employee.nbrDaysBefor = nbrDaysBetweenDates(now, permissions[i].startDate);
        let canApplicant = await DB.adminEmployee.findOne({where: {
          [Op.and]: [
            { isApplicant: true },
            { employeeId: employee.id },
            { AdmnistratorId: req.session.admin.id }
          ]
        }});
        if(canApplicant) {
          data.push(employee);
        }
      }            
    }
  };  
  return data;
}

const currentPermission = async ( nowDate ) => {
    let now = nowDate;
    //  Congee en cours
    let currents = await DB.permission.findAll({
      where : {
        [Op.and]: [
          { startDate: { [Op.lte]: now }}, // startDate <= now
          { startDate: { [Op.not]: null }}, // startDate is not null
          { endDate: { [Op.gte]: now }}, // endDate >= now
          { AdmnistratorId: { [Op.not]: null }},
          { AdmnistratorId: { [Op.gt]: 0 }},
        ]      
      }
    });
    var data = []
    if(currents) {    
      //  Trouver l'employe en permission
      for(i = 0; i < currents.length; i++ ) {      
        let employee = await DB.employee.findOne({ where: { id: currents[i].employeeId }});
        //  Leur fonction      
        if(employee) {        
          var employeeFunct = await DB.employeeFunction.findOne({
            where: { employeeId: employee.id },
            order: [['date', 'DESC']]
          });
          if (employeeFunct) {
              let fonction = await DB.function.findOne({
                  where: { id: employeeFunct.functionId }
              });
              if(fonction)
              employee.fonction = fonction;          
          }
          employee.permission = currents[i];
          //  Trouver le validateur
          let validateur = await DB.admin.findOne({ where: { id: employee.permission.AdmnistratorId }});
          if(validateur) {                    
            employee.permission.validateur = validateur;
          }        
  
          employee.restDay = nbrDaysBetweenDates(now, employee.permission.endDate);        
          data.push(employee);        
        }      
      }
    }        
    return data;
  }

  const rejectedPermission = async ( nowDate ) => {
    let now = nowDate;
    let rejectedVacs = await DB.permissionRejected.findAll({
      where: {              
           rejectedBy : {[Op.not]: null }
      }
    });
    let data = [];
    for( i = 0; i < rejectedVacs.length; i++) {
      let nbrDays = nbrDaysBetweenDates( rejectedVacs[i].createdAt, now );    
      if(nbrDays < 1 ) {
        
        let employee = await DB.employee.findOne({ where: { id: rejectedVacs[i].employeeId }});
        //  Leur fonction
        if(employee) {        
          employee.fonction = await functionController.getFunctionEmployee(employee.id);      
          employee.rejectedVac = rejectedVacs[i];  
          //  Trouver le rejecteur
          let rejector = await DB.admin.findOne({ where: { id: rejectedVacs[i].rejectedBy }});
          if(rejector) {                    
            employee.rejector = rejector;
          }                
          data.push(employee);
        }            
      }
      else {
        await rejectedVacs[i].destroy();
      }
    };  
    return data;
  }

module.exports = {
    getPermissionOnYear,
    requestPermission,
    nbrDaysBetweenDates,
    update,
    waitingPermiss,
    nextPermission,
    currentPermission,
    rejectedPermission,
}