'use strict';
const moment = require('moment');
const httpStatus = require('http-status');
const generateControllers = require('../../core/controllers');
const QRHelper = require('../../helpers/qr.helper');
const emailHelper = require('../../helpers/mail.helper');
const path = require("path");
const messages = require('../../helpers/messages.json');
const eventService = require('./event.service');
const eventReservationService = require('./events_reservations.service');
const eventInscriptionService = require('./events_inscriptions.service');
const { extractParamsFromRequest, handleErrorResponse, handleResultResponse } = require('../../helpers/controller.helper');

//PRUEBA
const SchemaValidator = require('../../middlewares/schemaValidator');
const eventValidation = require('./event.validations');
const Joi = require('joi');
const userService = require('../auth/user.service');


// Module Name
const MODULE_NAME = '[event.controller]';
const controllerOptions = { MODULE_NAME };

function generateMemberInscription (user, inscription, reservation) {
    let memberInscription = null;
    if (user && inscription) {
        memberInscription = {
                                marketing_memberId: null,
                                email: user.email,
                                name: user.name,
                                surname: user.surname,
                                source: inscription.source,
                                event_name: (inscription.event) ? inscription.event.name : 'N/A',
                                event_date: (inscription.event) ? inscription.event.init_date : 'N/A',
                                reservation_code: (reservation) ? reservation.reservation_code : null,
                                date_inscription: inscription.date,
                                code_ticket: inscription.code_ticket,
                                validated: inscription.validated,
                                color: (reservation) ? reservation.color : null,
                                description: ((reservation) ? reservation.description : 'Entrada').toUpperCase(),
                                entity: (reservation) ? reservation.Entity.name : user.entityId,
                                userId: user.id,
                                qrConfig: null,
                                qrCode: null,

                            }
    }

    return memberInscription;
};

function generateQRConfig (member) {
    let qrConfig = null;
    if (member) {
        qrConfig = {
            name: member.name,
            surname: member.surname,
            date: member.date_inscription,
            code: member.code_ticket,
            color: member.color,
        };
    };

    return qrConfig;
};

function generateHeaderMail (member) {
    let headerMail = null;
    if (member) {
        headerMail = {
            to: member.email,
            name: member.name + ' ' + member.surname,
            subject: ((member.validated) ? 'Entrada' : 'Lista de espera') + ' para el congreso ' + member.event_name + ' confirmada'
            };
    };

    return headerMail;
};

function generateBodyMail (member) {
    let bodyMail = null;
    if (member){
        bodyMail = {
            tipoEntrada: (member.validated) ? 'Entrada' : 'Lista de espera',
            descriptionEntrada: member.description,
            qrCode: member.qrCode,
            color: member.qrConfig.color,
            codeTicket: member.code_ticket,
            eventName: member.event_name,
            dateEvent: moment(member.event_date).format('D [de] MMMM [de] YYYY'),
            dateInscription: moment(member.date_inscription).format('DD/MM/YY HH:mm '),
        };
    }
    return bodyMail;
};

const extraControllers = {

    checkReservationCode: async (req, res, next) => {
        const params = extractParamsFromRequest(req, res, {});
        const appVersion = ((req && req.headers && req.headers['accept-version']) ? req.headers['accept-version'] : null);
        console.log('checkReservationCode - appVersion: ', appVersion); 
        console.log('checkReservationCode - PARAMS ', params); 
        
        const eventId = params.params.id;
        const encodedInvitationCode = params.params.encodedInvitationCode;
        
        const registrationCode = Buffer.from(req.params.encodedInvitationCode, 'base64').toString('ascii');

        try {
            const result = await eventReservationService._getReservaByCode(eventId, registrationCode);
            if (appVersion) {
                if ((appVersion == '1.0.0') || (appVersion == '1.0.1') || (appVersion == '1.0.2'))
                    return handleResultResponse(!!result, null, params, res, httpStatus.OK)
                else
                    return handleResultResponse(result, null, params, res, httpStatus.OK);              
            }
            else
                return handleResultResponse(!!result, null, params, res, httpStatus.OK);            
        } catch(error) {
            return handleErrorResponse(MODULE_NAME, 'checkReservationCode', error, res)
        }
    }, 

    //Funcion que devuelve:
    //1. Todas las inscripciones de un evento, cuando el usuario es administrador
    //2. Todas las inscripciones de un usuario, cuando no nos llega ningun param con id
    getInscriptions: async (req, res, next) => {
        const params = extractParamsFromRequest(req, res, {});
        const eventId = params.params.id;
        const userId = req.user.id;
        var result = null;

console.log(params, req.user.level);        
        if (eventId) {
            try {
                if (req.user.level = 8)
                    result = await eventInscriptionService._getInscriptionByEvent(eventId)
                else                
                    result = await eventInscriptionService._getInscriptionByEventAndUser(eventId, userId);

                return handleResultResponse(result, null, params, res, (result === null) ? httpStatus.NOT_FOUND : httpStatus.OK);
            } catch (error) {
                return handleErrorResponse(MODULE_NAME, 'getInscriptions', error, res)
            }
        }
        else{
            try {
                result = await eventInscriptionService._getInscriptionsUser(userId);
                return handleResultResponse(result, null, params, res, (result === null) ? httpStatus.NOT_FOUND : httpStatus.OK);
            } catch (error) {
                return handleErrorResponse(MODULE_NAME, 'getInscriptions', error, res)
            }
        }
    }, 

    getInscriptionsOfNextEventsCount: async (req, res, next) => {
        const params = extractParamsFromRequest(req, res, {});
        const userId = req.user.id;

        try {
            const result = await eventInscriptionService._getInscriptionsOfNextEventsUser(userId);
            console.log('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb');            
            return handleResultResponse({ count: result }, null, params, res, httpStatus.OK);
        } catch (error) {
            console.log('aaaaaaaaaaaaaaaaaaaaaaaaaaaa');
            return handleErrorResponse(MODULE_NAME, 'getInscriptionsOfNextEventsCount', error, res)
        }
    },

    getInscription: async (req, res, next) => {
        const params = extractParamsFromRequest(req, res, {});
        const inscriptionId = params.params.id;
        const userId = req.user.id;

        try {
            let inscription = await eventInscriptionService._getInscriptionById(inscriptionId); 
            if (!inscription) {
                return handleResultResponse("Inscripción no encontrada", null, params, res, httpStatus.NOT_FOUND);
            } else if (inscription.userId !== userId) {
                return handleResultResponse("Inscripción no encontrada", null, params, res, httpStatus.NOT_FOUND);
            }
console.log('inscripcion encontrada>>>>>>>>>>>>>>>>>>>>>>>>>>>', inscription);
            inscription = await inscription.toJSON();
            var member = generateMemberInscription(inscription.user, inscription, inscription.reservation);
            member.qrConfig = generateQRConfig(member);
            inscription.code_ticket_qr = await QRHelper.getInscriptionQRCode(member.qrConfig);
console.log('>>>>>>>voy a dar inscription');            
            return handleResultResponse(inscription, null, params, res, httpStatus.OK);                

        } catch (error) {
            return handleResultResponse("Error al buscar la inscripción", null, params, res, httpStatus.NOT_FOUND);
        }
    },

    findPartners: async (req, res, next) => {
        const params = extractParamsFromRequest(req, res, {});
        try {
            const result = await eventReservationService._getPartners(params.params.id);
            return handleResultResponse(result, result.count, params, res, httpStatus.OK);
        } catch (error) {
            return handleErrorResponse(MODULE_NAME, 'findPartners', error, res)
        }
    },

    findColleges: async (req, res, next) => {
        const params = extractParamsFromRequest(req, res, {});
        try {
            const result = await eventReservationService._getColleges(params.params.id);
            return handleResultResponse(result, result.count, params, res, httpStatus.OK);
        } catch (error) {
            return handleErrorResponse(MODULE_NAME, 'findPartners', error, res)
        }
    },

    validateInscription: async (req, res, next) => {
        const params = extractParamsFromRequest(req, res, {});
        const user = req.user;
        const inscriptionId = params.params.id;        
       
        try {
            let inscription = await eventInscriptionService._getInscriptionById(inscriptionId);
//console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>><Inscripcion a Validar:');
//console.log(inscription);

            //Si la inscripcion no existe o ya está validada no hago nada
            if (!inscription)
                return handleResultResponse("Inscription no encontrada", null, params, res, httpStatus.NOT_FOUND)
            else if (inscription.validated)
                return handleResultResponse("Inscripción validada", null, params, res, httpStatus.OK);            

            //Si la inscripción es lista de espera de una reserva
            if (inscription.reservationId)
            {
                return handleResultResponse("Inscription a validar viene por reserva hay que implementarlo", null, params, res, httpStatus.NOT_FOUND);
//                console.log('Tengo reservation>>>>>>>>>>>>>>>>>>', inscription.reservationId);
//                NewConfirmed = await eventInscriptionService._getCountInscriptionsWithReservation(EventOrReservationChangeId)
//                marketingListId = (await eventReservationService._getReservaById(EventOrReservationChangeId)).marketing_list;
//                if (!await eventReservationService._updateConfirmedReservation(EventOrReservationChangeId, NewConfirmed))
//                    return handleResultResponse("Error al eliminar inscripción, no puedo cambiar confirmados a la reserva asociada", null, params, res, httpStatus.NOT_FOUND);
            }
            //Si la inscripcion es lista de espera del evento
            else if (inscription.overflowEventId) {            

                const OverflowEventId = inscription.overflowEventId;

                if (await eventInscriptionService._validateInscription(inscription.id, user.id) > 0) {
                    inscription.validated = true;
console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>><Inscripcion validada');
                    var NewConfirmedOverflow = await eventInscriptionService._getCountInscriptionsWithOverflowEventId(OverflowEventId);
                    var NewConfirmedEvent = await eventInscriptionService._getCountInscriptionsWithoutReservationAndOverflow(inscription.eventId);
                    var marketingListIdOverflow = (await eventService._getEvent(OverflowEventId)).marketing_list;
                    var marketingListIdEvent = (await eventService._getEvent(inscription.eventId)).marketing_list;                    
console.log('>>>>>>>>>>>>>>><NewConfirmedOverflow: ', NewConfirmedOverflow);
console.log('>>>>>>>>>>>>>>><NewConfirmedEvent: ', NewConfirmedEvent);                    

                    //Actualizamos aforos
                    if (!await eventService._updateConfirmedEvent(OverflowEventId, NewConfirmedOverflow))
                        return handleResultResponse("Error al validad inscripción, no puedo cambiar confirmados a la lista de espera", null, params, res, httpStatus.NOT_FOUND);
                    if (!await eventService._updateConfirmedEvent(inscription.eventId, NewConfirmedEvent))
                        return handleResultResponse("Error al validad inscripción, no puedo cambiar confirmados al evento", null, params, res, httpStatus.NOT_FOUND);
                    
                    //Eliminamos miembro de la lista de mailchimp a la que está asociado
                    await eventInscriptionService._deleteMember(marketingListIdOverflow, inscription.marketing_memberId);                        

                    var member = generateMemberInscription(inscription.user, inscription, inscription.reservation);  
                    member.marketing_memberId = await eventInscriptionService._addMember(marketingListIdEvent, member);
                    eventInscriptionService._updateMarketingMemberOfInscription(inscription.id, member.marketing_memberId);
                    member.qrConfig = generateQRConfig(member);
                    member.qrCode = await QRHelper.getInscriptionQRCode(member.qrConfig);

console.log('mandar correo>>>>>>>>>>>>>>>>>>>>> ', member);                                                          
                    //Mandar correo de confirmacion de desinscripcion
                    try {
                        emailHelper.sendTicket(generateHeaderMail(member), generateBodyMail(member))
                    } catch (error) {
                        console.log('No se ha podido mandar email con entrada');
                    };
                };

                return handleResultResponse("Inscripción validada", null, params, res, httpStatus.OK);
            }
            else
                return handleResultResponse("No se pudo validar inscripción", null, params, res, httpStatus.NOT_FOUND);

        } catch (error) {
            return handleResultResponse("Error al validar inscripción", null, params, res, httpStatus.NOT_FOUND);
        }

    },

    deleteInscription: async (req, res, next) => {
        const params = extractParamsFromRequest(req, res, {});
        const user = req.user;
        const inscriptionId = params.params.id;
        
        try {
            const inscription = await eventInscriptionService._getInscriptionById(inscriptionId); 
console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>><Inscripcion a borrar:');
console.log(inscription);
            if (!inscription || (inscription.userId !== user.id)) 
                return handleResultResponse("Inscription no encontrada", null, params, res, httpStatus.NOT_FOUND);

            //Borramos inscripcion y descontamos asistentes
            if (await eventInscriptionService._deleteInscription(inscription.id) > 0){
console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>><Inscripcion borrada');
                const EventOrReservationChangeId = ((inscription.reservationId) ? inscription.reservationId : ((inscription.overflowEventId) ? inscription.overflowEventId : inscription.eventId));
                let NewConfirmed = 0;
                let marketingListId = null;

                if (inscription.reservationId != null){
                    console.log('Tengo reservation>>>>>>>>>>>>>>>>>>', inscription.reservationId);                
                    NewConfirmed = await eventInscriptionService._getCountInscriptionsWithReservation(EventOrReservationChangeId)
                    marketingListId = (await eventReservationService._getReservaById(EventOrReservationChangeId)).marketing_list;
                }
                else if (inscription.overflowEventId != null) {
                    console.log('Tengo overflow>>>>>>>>>>>>>>>>>>', inscription.overflowEventId);                                    
                    NewConfirmed = await eventInscriptionService._getCountInscriptionsWithOverflowEventId(EventOrReservationChangeId);
                    marketingListId = (await eventService._getEvent(EventOrReservationChangeId)).marketing_list;
                }
                else if (inscription.eventId != null) {
                    NewConfirmed = await eventInscriptionService._getCountInscriptionsWithoutReservationAndOverflow(EventOrReservationChangeId);
                    marketingListId = (await eventService._getEvent(EventOrReservationChangeId)).marketing_list;                    
                }

                //Actualizamos aforo del evento o de la reserva
                if (inscription.reservationId != null){
                    console.log('>>>>>>>>>>>>>>Voy a actualizar aforo reserva', EventOrReservationChangeId);
console.log('>>>>>>>>>>>>>> ', NewConfirmed);
                    if (!await eventReservationService._updateConfirmedReservation(EventOrReservationChangeId, NewConfirmed))
                        return handleResultResponse("Error al eliminar inscripción, no puedo cambiar confirmados a la reserva asociada", null, params, res, httpStatus.NOT_FOUND);
                }
                else {
                    console.log('>>>>>>>>>>>>>>Voy a actualizar aforo evento', EventOrReservationChangeId);                    
console.log('>>>>>>>>>>>>>> ', NewConfirmed);
                    if (!await eventService._updateConfirmedEvent(EventOrReservationChangeId, NewConfirmed))
                        return handleResultResponse("Error al eliminar inscripción, no puedo cambiar confirmados a la inscripcion", null, params, res, httpStatus.NOT_FOUND);

                }

                //Desinscribimos de mailchimp y mandamos correo de confirmacion de desinscripcion
                await eventInscriptionService._deleteMember(marketingListId, inscription.marketing_memberId);                

                var member = generateMemberInscription(inscription.user, inscription, inscription.reservation);
                member.qrConfig = generateQRConfig(member);
                member.qrCode = await QRHelper.getInscriptionQRCode(member.qrConfig);

                let headerMail = generateHeaderMail(member);
                headerMail.subject = 'Cancelación de ' + headerMail.subject;

                try {
                    emailHelper.sendCancelacion(headerMail, generateBodyMail(member))
                } catch (error) {
                    console.log('No se ha podido mandar email con entrada');
                };


                return handleResultResponse("Inscripción eliminada", null, params, res, httpStatus.DELETEOK);                
            }
            else
                return handleResultResponse("No se pudo eliminar inscripción", null, params, res, httpStatus.NOT_FOUND);

        } catch (error) {
            return handleResultResponse("Error al eliminar inscripción", null, params, res, httpStatus.NOT_FOUND);
        }

    },

    //Esta función se puede llamar desde APP y desde WEB
    createInscription: async(req, res, next) => {
        const params = extractParamsFromRequest(req, res, {});
console.log('CREATE INSCRIPTION>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>< ', params);
        //Iniciamos entidades relacionadas con la inscripción.
        let dataUser = {
            id: (req.user) ? req.user.id : null,
            phone: (req.user) ? req.user.phone : null, //((req.body.phone != '+34') ? req.body.phone : null), lo quitamos de momento por la de movistar
            name: (req.user) ? req.user.name : req.body.name,
            surname: (req.user) ? req.user.surname : req.body.surname,
            email: (req.user) ? req.user.email : req.body.email,
            entityId: null,
            userResult: (req.user) ? req.user : null,
        }
        
        let dataInscription = {
            eventId: params.params.id,
            reservationCode: (req.user) ? req.body.code : Buffer.from(req.body.code, 'base64').toString('ascii'),
            type: (req.body.code) ? 'reservation' : 'regular',
            source: (req.user) ? 'app' : 'web', //En el caso de tener ya usuario viene por APP sino viene por web
            validated: null, //si no esta validado la inscripción es a la lista de espera
            inscriptionsWithoutReservationAndOverflowCount: null, //nº total de inscritos sin reserva y sin overflow asignada
            inscriptionsWithReservationCount: null, //nº total de inscritos a la reserva asignada
            event: null,
            reservation: null,
            inscription: null,
        }

        console.log('DATAUSER_INICIAL>>>>>>>>>>>>>>>>>>>>');
        console.log(dataUser);
        console.log('DATAINSCRIPTION_INICIAL>>>>>>>>>>>>>>>>>>');        
        console.log(dataInscription);


        //SI VIENE CODIGO DE RESERVA, RECUPERAMOS LA RESERVA Y EL EVENTO
        if (dataInscription.reservationCode) {
            try {
                dataInscription.reservation = await eventReservationService._getReservaByCode(dataInscription.eventId, dataInscription.reservationCode);            
                if (dataInscription.reservation) {
                    dataInscription.reservation = await dataInscription.reservation.toJSON();
                    dataInscription.event = dataInscription.reservation.Event;
                } else {
                    // No se ha encontrado
                    return handleResultResponse("Código de reserva no encontrado", null, params, res, httpStatus.NOT_FOUND);
                }
            } catch(error) {
                return handleErrorResponse(MODULE_NAME, 'createInscription', error, res)
            }
        }
        //SOLO RECUPERAMOS EL EVENTO
        else {
            try {
                dataInscription.event = await eventService._getEvent(dataInscription.eventId);
                if (dataInscription.event) {
                    dataInscription.event = await dataInscription.event.toJSON();            
                } else {
                    // No se ha encontrado
                    return handleResultResponse("Evento no encontrado", null, params, res, httpStatus.NOT_FOUND);
                }
            } catch(error) {
                return handleErrorResponse(MODULE_NAME, 'createInscription', error, res)   
            }
        } 

        console.log('>>>>>>>>>>>>>>>>>>>>>>>esta es la reserva y el evento al que quiere inscribirse');
        console.log(dataInscription.reservation);
        console.log(dataInscription.event);      
        //Asignamos a los datos del usuario a crear, el id de la entidad a la que pertenece, este caso solo es necesario cuando viene la inscripción por web ya que hay que crear un usuario nuevo
        if (dataInscription.reservation)
           dataUser.entityId = dataInscription.reservation.entityId;

        //creamos o recuperamos el usuario teniendo en cuenta que pude venir por APP o WEB
        //si viene por web se tendra en cuenta el email y si viene por APP el phone para buscar
        try {
//CHAPUZA PARA PODER DAR DE ALTA USUARIOS CON EL MISMO CORREO ELECTRONICO, PERO DISTINTO NOMBRE Y APELLIDO.
            if (req.user) //? 'app' : 'web', //En el caso de tener ya usuario viene por APP sino viene por web
                dataUser.userResult = await userService._getOrCreateUser(dataUser)
            else
                dataUser.userResult = await userService._getOrCreateUserWEB(dataUser);
            
            
            if (!dataUser.userResult) {
                // No se ha encontrado
                return handleResultResponse("No se ha podido crear o encontrar el usuario dado", null, params, res, httpStatus.NOT_FOUND);
            };
        } catch(error) {
            return handleErrorResponse(MODULE_NAME, 'createInscription', error, res);
        }

        console.log('>>>>>>>>>>>>>>>>>>>>>>este es el usuario que quiere inscribirse');
        console.log(dataUser.userResult);
        

        try  {

            //Comprobamos que el usuario no tenga ya inscripcion para ese evento
            dataInscription.inscription = await eventInscriptionService._getInscriptionByEventAndUser(dataInscription.event.id, dataUser.userResult.user.id);
            if (dataInscription.inscription) {
console.log('esta es la inscripcion que ya tengo>>>>>>>>>>>>>>>>>>>>><');
console.log(dataInscription.inscription);
                //Devuelvo la reserva que ya tiene hecha el usuario
                if ((!dataInscription.inscription.reservationId) || (dataInscription.inscription.reservationId == dataInscription.reservation.id)) 
                    return handleResultResponse(dataInscription.inscription, null, params, res, httpStatus.OK);                                        

                //ACTUALIZAMOS LA RESERVA DE LA INSCRIPCION CON LA NUEVA Y CAMBIAMOS COMFIRMADOS DEVOLVIENDO LA INSCRIPCIÓN CON LA NUEVA RESERVA    
                let CountConfirmedOldReservation = await eventInscriptionService._getCountInscriptionsWithReservation(dataInscription.inscription.reservationId);                    
                --CountConfirmedOldReservation;
console.log('actualizo confirmados de la reserva anterior');                
                await eventReservationService._updateConfirmedReservation(dataInscription.inscription.reservationId, CountConfirmedOldReservation);

                let CountConfirmedNewReservation = await eventInscriptionService._getCountInscriptionsWithReservation(dataInscription.reservation.id);                                        
                ++CountConfirmedNewReservation;
console.log('actualizo confirmados de la nueva reserva');                                
                await eventReservationService._updateConfirmedReservation(dataInscription.reservation.id, CountConfirmedNewReservation);
                await eventInscriptionService._updateReservationOfInscription(dataInscription.inscription.id, dataInscription.reservation.id);

                dataInscription.inscription = await eventInscriptionService._getInscriptionById(dataInscription.inscription.id);
                return handleResultResponse(dataInscription.inscription, null, params, res, httpStatus.OK);                    
            } 
            //TENEMOS QUE CREAR INSCRIPCIÓN
            else {

                //CON CODIGO DE RESERVA SE MODIFICA EL CONFIRMED DE LA RESERVA, YA QUE SE DESCONTARA DEL AFORO DE LA RESERVA          
                if (dataInscription.reservation) {
                    dataInscription.inscriptionsWithReservationCount = await eventInscriptionService._getCountInscriptionsWithReservation(dataInscription.reservation.id);
                    ++dataInscription.inscriptionsWithReservationCount;  

                    console.log('me inscribo por reserva>>>>>>>>>>>>>>>>>>>>>>>>>>><< con asistentes: ', dataInscription.reservation.assistants);
                    console.log(dataInscription.reservation.sold_out);
                    console.log(dataInscription.inscriptionsWithReservationCount);

                    //COMPROBAMOS SI ES VALIDO O HAY QUE APUNTARLE A LA LISTA DE ESPERA DE LA RESERVA
                    if ((dataInscription.reservation.sold_out == 0) && (dataInscription.reservation.assistants >= dataInscription.inscriptionsWithReservationCount)) {
                        dataInscription.validated = true;

                        //Actualizamos aforo de la lista de espera de la reserva y creamos inscripcion en la lista de espera de la reserva
                        if (await eventReservationService._updateConfirmedReservation(dataInscription.reservation.id, dataInscription.inscriptionsWithReservationCount))
                            dataInscription.inscription = await eventInscriptionService._createInscription(dataInscription.event.id,
                                                                                                           dataUser.userResult.user.id, 
                                                                                                           dataInscription.type, 
                                                                                                           dataInscription.validated,
                                                                                                           dataInscription.source, 
                                                                                                           dataInscription.reservation.id,
                                                                                                           null)
                        else
                            return handleResultResponse("No se ha podido actualizar el aforo de la reserva", null, params, res, httpStatus.NOT_FOUND);                    

                        //Ponemos la reserva en SOLD_OUT para que no se pueda apuntar nadie más
                        if (dataInscription.reservation.assistants == dataInscription.inscriptionsWithReservationCount)
                            await eventReservationService._updateSoldOutReservation(dataInscription.reservation.id, true);                        
                    }
                    // APUNTARSE A LISTA DE ESPERA SI SE PUEDE
                    else {
                        if (dataInscription.reservation.allow_overflow === true) {
                            dataInscription.validated = false;
                            dataInscription.inscriptionsWithReservationCount = await eventInscriptionService._getCountInscriptionsWithReservation(dataInscription.reservation.overflow_reservationId);
                            ++dataInscription.inscriptionsWithReservationCount;

//                            if (dataInscription.reservation.assistants >= dataInscription.inscriptionsWithReservationCount) {
                            //Actualizamos aforo de la reserva y creamos inscripcion
                            if (await eventReservationService._updateConfirmedReservation(dataInscription.reservation.overflow_reservationId, dataInscription.inscriptionsWithReservationCount))
                                dataInscription.inscription = await eventInscriptionService._createInscription(dataInscription.event.id,
                                                                                                               dataUser.userResult.user.id,
                                                                                                               dataInscription.type,
                                                                                                               dataInscription.validated,
                                                                                                               dataInscription.source,
                                                                                                               dataInscription.reservation.overflow_reservationId,
                                                                                                               null)
                            else
                                return handleResultResponse("No se ha podido actualizar el aforo de la reserva", null, params, res, httpStatus.NOT_FOUND);                    
                        }
                        else
                            return handleResultResponse("Aforo completo de la reserva y no hay lista de espera", null, params, res, httpStatus.NOT_FOUND);                                                  
                     }
                }
                 //SIN CODIGO DE RESERVA SE MODIFICA EL CONFIRMED DEL EVENTO, YA QUE SE DESCONTARA DEL AFORO DEL EVENTO
                else {
                    dataInscription.inscriptionsWithoutReservationAndOverflowCount = await eventInscriptionService._getCountInscriptionsWithoutReservationAndOverflow(dataInscription.event.id);
                    ++dataInscription.inscriptionsWithoutReservationAndOverflowCount;


                    //COMPROBAMOS SI ES VALIDO O HAY QUE APUNTARLE A LA LISTA DE ESPERA DEL EVENTO
                    if ((dataInscription.event.sold_out == 0) && (dataInscription.event.assistants >= dataInscription.inscriptionsWithoutReservationAndOverflowCount)) {
                        dataInscription.validated = true;
                        //Actualizamos aforo del evento y creamos inscripcion
                        if (await eventService._updateConfirmedEvent(dataInscription.event.id, dataInscription.inscriptionsWithoutReservationAndOverflowCount))
                            dataInscription.inscription = await eventInscriptionService._createInscription(dataInscription.event.id,
                                                                                                           dataUser.userResult.user.id,
                                                                                                           dataInscription.type,
                                                                                                           dataInscription.validated,
                                                                                                           dataInscription.source,
                                                                                                           null,
                                                                                                           null)
                        else
                            return handleResultResponse("No se ha podido actualizar el aforo del evento", null, params, res, httpStatus.NOT_FOUND);  

                        //Ponemos el evento en SOLD_OUT
                        if (dataInscription.event.assistants == dataInscription.inscriptionsWithoutReservationAndOverflowCount) 
                            await eventService._updateSoldOutEvent(dataInscription.event.id, true);                        
                    }
                    // APUNTARSE A la lista de espera si se puede
                    else {
                        if (dataInscription.event.allow_overflow === true) {
                            dataInscription.validated = false;
                        
                            //Actualizamos aforo de la lista de espera del evento y creamos inscripcion
console.log('evento de lista de espera que debo actulizar sus confirmados>>>>>>>>>>>>>>>>>>>>>', dataInscription.event.overflow_eventId); 
                            //recuperamos la cantidad de apuntados al evento overflow a lista de espera 
                            const ConfirmedWaitList = await eventInscriptionService._getCountInscriptionsWithOverflowEventId(dataInscription.event.overflow_eventId);
                            console.log('cantidad apuntados al evento padre>>>>>>>>>>>>>>>>>>>>>', dataInscription.inscriptionsWithoutReservationAndOverflowCount);      
                            console.log('cantidad apuntados al evento de lista de espera asociado>>>>>>>>>>>>>>>>>>>>>', ConfirmedWaitList);                                  


                            
                            
                            if (await eventService._updateConfirmedEvent(dataInscription.event.overflow_eventId, ConfirmedWaitList)) {
//console.log('voy a crearrrrrr la inscripcion');                            
                                dataInscription.inscription = await eventInscriptionService._createInscription(dataInscription.event.id, 
                                                                                                               dataUser.userResult.user.id, 
                                                                                                               dataInscription.type, 
                                                                                                               dataInscription.validated, 
                                                                                                               dataInscription.source, 
                                                                                                               null,
                                                                                                               dataInscription.event.overflow_eventId);
                            }
                            else {
console.log('No se ha podido actualizar el aforo del evento');                                                            
                                return handleResultResponse("No se ha podido actualizar el aforo del evento", null, params, res, httpStatus.NOT_FOUND);  
                            }                                
                        }
                        else
                            return handleResultResponse("Aforo completo y no hay lista de espera", null, params, res, httpStatus.NOT_FOUND);                          
                    }
                 
                }    
            }

        } catch (error) {
            return handleErrorResponse(MODULE_NAME, 'createInscription', error, res);
        }


        const marketingListOfInscription = dataInscription.event.marketing_list;
/*AHORA SE ALMACENA TODO EN UNA ÚNICA LISTA DE MAILCHIMP, QUE ES LA DEL EVENTO 
(si en un futuro se quiere tener listas independientes, bastaría con tratarlo aqui los campos de marketinglist de la reserva ...)
        if (dataInscription.inscription.reservationId)
            marketingListOfInscription = dataInscription.reservation.marketingList
        else if (dataInscription.inscription.overflowEventId)
            marketingListOfInscription = (await _getEvent(dataInscription.inscription.overflowEventId)).marketingList;
        else 
            marketingListOfInscription = dataInscription.event.marketingList;
*/
        //Creamos objeto member para facilitar inserción en mailchimp y envio de correo
        var member = generateMemberInscription(dataUser.userResult.user, dataInscription.inscription, dataInscription.reservation);
        //En este caso al ser una inscripcion recien creada hay que asignar los datos del evento desde el evento
        member.event_name = dataInscription.event.name;
        member.event_date = dataInscription.event.init_date;        

        try
        {
            member.marketing_memberId = await eventInscriptionService._addMember(marketingListOfInscription, member);
            eventInscriptionService._updateMarketingMemberOfInscription(dataInscription.inscription.id, member.marketing_memberId);
        } catch (error) {
               console.log('No se ha podido añadir email a mailchimp');
        };


        member.qrConfig = generateQRConfig(member);        
        member.qrCode = await QRHelper.getInscriptionQRCode(member.qrConfig);        

console.log('Mandamos mail con entrada>>>>>>>>>>>>>>>>>>>>>>>>>>>');        
//console.log(headerMail, bodyMail);
        
        try
        {
            if (member.validated)
                emailHelper.sendTicket(generateHeaderMail(member), generateBodyMail(member))
            else
                emailHelper.sendListaEspera(generateHeaderMail(member), generateBodyMail(member));
        } catch (error) {
            console.log('No se ha podido mandar email con entrada');
        };

        return handleResultResponse(await dataInscription.inscription.toJSON(), null, params, res, httpStatus.CREATED)          
    },

    getQRCodeInscription: async (req, res, next) => {
        const params = extractParamsFromRequest(req, res, {});
        const inscriptionId = params.params.id;
        const userId = req.user.id;

        try {
            const inscription = await eventInscriptionService._getInscriptionById(inscriptionId);
            if (!inscription) {
                return handleResultResponse("Inscription no encontrada", null, params, res, httpStatus.NOT_FOUND);
            } else if (inscription.userId !== userId) {
                return handleResultResponse("Inscription no encontrada", null, params, res, httpStatus.NOT_FOUND);                
            }

            //Creamos objeto member para facilitar inserción en mailchimp y envio de correo
            var member = generateMemberInscription(req.user, inscription.inscription, inscription.reservation);
            member.qrConfig = generateQRConfig(member);
            member.qrCode = await QRHelper.getInscriptionQRCode(member.qrConfig);

            return handleResultResponse(member.qrCode, null, params, res, httpStatus.OK);

        } catch (error) {
            return handleResultResponse("Error al buscar la inscripción", null, params, res, httpStatus.NOT_FOUND);
        }
    },

    checkInscription: async (req, res, next) => {
        const params = extractParamsFromRequest(req, res, {});
        var eventId = params.params.id;
        var email = params.params.email;

        try {
            const user = await userService._getUserByEmail(email);
            if (user) {
                const result = await eventInscriptionService._getInscriptionByEventAndUser(eventId, user.id)
                if (result) 
                    return handleResultResponse(result.stateText, null, params, res, httpStatus.OK);
            }

            return handleResultResponse("No hay inscripción con ese email", null, params, res, httpStatus.NOT_FOUND);

        } catch (error) {
            return handleErrorResponse(MODULE_NAME, 'checkInscription', error, res)
        }
    },

    sendMailTicket: async (req, res, next) => {
        const params = extractParamsFromRequest(req, res, {});
        const inscriptionId = params.params.id;
        const user = req.user;
        try {
            const inscription = await eventInscriptionService._getInscriptionById(inscriptionId);
            if (!inscription) 
                return handleResultResponse("Inscription no encontrada", null, params, res, httpStatus.NOT_FOUND);                

            console.log('soy administrador?????? ', user);    
//            if (inscription.userId !== user.id)
//                return handleResultResponse("Inscription no encontrada", null, params, res, httpStatus.NOT_FOUND);

            const userInscription = await userService._getUserById(inscription.userId);

            //Creamos objeto member para facilitar inserción en mailchimp y envio de correo
            var member = generateMemberInscription(userInscription, inscription, inscription.reservation);
            member.qrConfig = generateQRConfig(member);
            member.qrCode = await QRHelper.getInscriptionQRCode(member.qrConfig);

            console.log('Mandamos mail con entrada>>>>>>>>>>>>>>>>>>>>>>>>>>>');
            //console.log(headerMail, bodyMail);

            try {
                if (member.validated)
                    emailHelper.sendTicket(generateHeaderMail(member), generateBodyMail(member))
                else
                    emailHelper.sendListaEspera(generateHeaderMail(member), generateBodyMail(member));
            } catch (error) {
                console.log('No se ha podido mandar email con entrada');
            };

            return handleResultResponse(null, null, params, res, httpStatus.OK);

        } catch (error) {
            return handleResultResponse("Error al buscar la inscripción", null, params, res, httpStatus.NOT_FOUND);
        }
    },

    getReservationsExcel: async (req, res, next) => {
        const params = extractParamsFromRequest(req, res, {});
        const eventId = params.params.id;
        const type = params.params.type;
        const userId = req.user.id;

        const reservations = await eventReservationService._getReservationsExcel(req.user, eventId, null, type, function(result, status){
            if (result.messenger.code == "S99001") {
                console.log(result);
                res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
                res.setHeader('Content-Disposition', 'attachment; filename=' + result.data.name);
                res.attachment(result.data.name);
                res.download(path.resolve(result.data.path), result.data.name);
            } else {
                res.status(status).json(result);
            }
        })
    },

    getInscripcionsExcel: async (req, res, next) => {
        const params = extractParamsFromRequest(req, res, {});
        const eventId = params.params.id;
        const userId = req.user.id;

        const inscriptions = await eventInscriptionService._getInscriptionsExcel(req.user, eventId, function (result, status) {
            if (result.messenger.code == "S99001") {
                console.log(result);
                res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
                res.setHeader('Content-Disposition', 'attachment; filename=' + result.data.name);
                res.attachment(result.data.name);
                res.download(path.resolve(result.data.path), result.data.name);
            } else {
                res.status(status).json(result);
            }
        })
    },
    

};

module.exports = generateControllers(eventService, extraControllers, controllerOptions);

