/* global Venue */
"use strict";

const _ = require("lodash");
const moment = require("moment");
const { generateService, parseParamsToFindOptions } = require("../../helpers/service.helper");
const models = require("../../core/models");
const Sequelize = require("sequelize");
const xlsx = require("node-xlsx");
const fs = require("fs");
const cdnHelper = require("../../helpers/cdn.helper");

moment.locale("es");

function generateNewCodeTicket() {
  let longitud = 8;
  let timestamp = +new Date();

  var _getRandomInt = function (min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  };

  var ts = timestamp.toString();
  var parts = ts.split("").reverse();
  var id = "";

  for (var i = 0; i < longitud; ++i) {
    var index = _getRandomInt(0, longitud - 1);
    id += parts[index];
  }

  return id;
}

const extraMethods = {
  _fillInscriptionColor: (inscription) => {
    if (inscription && inscription.type) {
      const isVirtual = inscription.type === "online" || inscription.type === "online group";
      if (inscription.reservationId === null && !isVirtual) {
        // Inscripción normal
        inscription.color = "green";
      }
    }

    return inscription;
  },

  _fillInscriptionsColor: (inscriptions) => {
    if (inscriptions && inscriptions.length) {
      return inscriptions.map(extraMethods._fillInscriptionColor);
    } else {
      return inscriptions;
    }
  },

  _getInscriptionById: (id) => {
    return models.EventInscription.scope(["includeEventAndVenue", "includeReservation", "defaultScope"]).findOne({
      where: {
        id: id,
      },
    });
  },

  _getInscriptionByEventAndUser: (eventId, userId) => {
    return models.EventInscription.scope(["includeEventAndVenue"]).findOne({
      where: {
        eventId: eventId,
        userId: userId,
      },
    });
  },

  _getInscriptionByEvent: (eventId) => {
    return models.EventInscription.scope("defaultScope").findAll({
      where: {
        eventId: eventId,
        type: ["onsite", "onsite group", "regular", "reservation"],
      },
    });
  },

  _getInscriptionOnlineByEvent: (eventId) => {
    return models.EventInscriptionOnline.scope("defaultScope").findAll({
      where: {
        eventId: eventId,
        //type: ["online", "online group"],
      },
    });
  },

  _getInscriptionByEventAndValidated: (eventId, validated) => {
    return models.EventInscription.scope("defaultScope").findAll({
      where: {
        validated: validated,
        eventId: eventId,
      },
    });
  },

  _getInscriptionByEventFromPartner: (eventId) => {
    return models.EventInscription.scope("defaultScope").findAll({
      where: {
        eventId: eventId,
        reservationId: { [Sequelize.Op.ne]: null },
      },
    });
  },

  _getInscriptionsUser: (userId) => {
    return models.EventInscription.scope("includeEventAndVenue", "includeReservation").findAll({
      attributes: {
        exclude: [
          "marketing_memberId",
          "overflowEventId",
          "createdAt",
          "updatedAt",
          "userId",
          "eventId",
          "validateUserId",
        ],
      },
      where: {
        userId: userId,
      },
    });
  },

  _getInscriptionsOfNextEventsUser: (userId) => {
    return models.EventInscription.count({
      include: [
        {
          model: models.Event,
          as: "event",
          where: {
            end_date: { [Sequelize.Op.gte]: moment().utc() },
          },
        },
      ],
      where: { userId: userId },
    });
  },

  //Nos devuelve el número de inscripciones confirmadas para ese evento sin tener en cuenta reservas ni lista de espera
  _getCountInscriptionsWithoutReservationAndOverflow: (eventId) => {
    return models.EventInscription.count({
      where: {
        eventId: eventId,
        reservationId: null,
        overflowEventId: null,
        type: ["onsite", "onsite group", "regular", "reservation"],
      },
    });
  },

  //Nos devuelve el número de inscripciones realizadas con esa reserva
  _getCountInscriptionsWithReservation: (reservationId) => {
    return models.EventInscription.count({
      where: {
        reservationId: reservationId,
      },
    });
  },

  //Nos devuelve el número de inscripciones realizadas con esa reserva
  _getCountInscriptionsWithOverflowEventId: (overflowEventId) => {
    return models.EventInscription.count({
      where: {
        overflowEventId: overflowEventId,
      },
    });
  },

  _updateReservationOfInscription: (id, reservationId) => {
    return models.EventInscription.update(
      {
        reservationId: reservationId,
      },
      {
        where: { id: id },
      }
    );
  },

  _updateMarketingMemberOfInscription: (id, marketingMemberId) => {
    return models.EventInscription.update(
      {
        marketing_memberId: marketingMemberId,
      },
      {
        where: { id: id },
      }
    );
  },

  _createInscription: (eventId, userId, type, validated, source, reservationId, overflowEventId) => {
    console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<valores de la inscripcion");
    console.log(eventId, userId, type, validated, source, reservationId, overflowEventId);

    return new Promise(function (resolve, reject) {
      models.EventInscription.create({
        eventId: eventId,
        date: moment().utc(),
        userId: userId,
        type: type,
        code_ticket: "ENT-" + generateNewCodeTicket(),
        source: source,
        validated: validated,
        reservationId: reservationId,
        overflowEventId: overflowEventId,
      })
        .then(function (result) {
          resolve(result);
        })
        .catch(function (error) {
          reject(error);
        });
    });
  },

  _deleteInscription: (id) => {
    //habria que poner el idusuario para asegurar que otro usuario no borra una inscripcion de otro

    return models.EventInscription.destroy({
      where: {
        id: id,
      },
    });
  },

  _deleteInscriptionByUser: (userId) => {
    return models.EventInscription.destroy({
      where: {
        userId: userId,
      },
    });
  },

  //Elimina todas las inscripciones de una determinada reserva/invitacion
  _deleteInscriptionsByReservation: (reservationId) => {
    return models.EventInscription.destroy({
      where: {
        reservationId: reservationId,
      },
    });
  },

  //Validamos la inscripcion la quitamos de las lista de espera y asignamos el usuario que la ha validado
  _validateInscription: (inscriptionId, userId) => {
    return models.EventInscription.update(
      {
        validated: true,
        overflowEventId: null,
        validateUserId: userId,
      },
      {
        where: {
          id: inscriptionId,
        },
      }
    );
  },

  //Validamos la inscripcion del tutor que hizo la reserva
  _validateInscriptionTutorOfReservation: (reservationId, userId) => {
    return models.EventInscription.update(
      {
        validated: true,
        overflowEventId: null,
        validateUserId: userId,
      },
      {
        where: {
          reservationId: reservationId,
          userId: userId,
        },
      }
    );
  },

  _getInscriptionsWithoutMemberId: (eventId) => {
    return models.EventInscription.scope(["includeEventAndVenue", "includeReservation", "defaultScope"]).findAll({
      where: {
        eventId: eventId,
        marketing_memberId: null,
      },
    });
  },

  _getInscriptionsExcel: (user, eventId, callback) => {
    console.log("DESCARGA EXCEL INSCRIPCIONES TOTALES>>>>>>>> ");
    console.log(">>>>>>>>>>>>>>>>>>>><consulta con eventId:", eventId);

    models.EventInscription.findAll({
      where: {
        eventId: eventId,
        type: ["onsite", "onsite group", "regular", "reservation"],
      },
      include: [
        {
          model: models.Event,
          as: "event",
          attributes: ["id", "name"],
        },
        /*            {
                model: models.User,
                as: 'user' ,
                include: [{ model: models.Entity, attributes: ['id', 'name'], required: false}] 
            }],
        */
      ],
      order: [
        //                [{ model: models.Entity }, 'name', 'ASC'],
        //                [{ model: models.User },'name', 'ASC'],
      ],
    })
      .then(function (inscriptions) {
        //            console.log(inscriptions[c]);
        if (inscriptions.length) {
          var data = [];

          data.push(["Centro educativo", "Número de entrada", "Nombre", "Apellidos", "Email", "Válido"]);

          for (var c = 0; c < inscriptions.length; c++) {
            var inscription = inscriptions[c];
            //                    console.log(inscription);

            var code = inscription.code_ticket;
            var name = inscription.user.name;
            var surname = inscription.user.surname ? inscription.user.surname : "";
            var email = inscription.user.email;
            var college = inscription.user.entityId ? inscription.user.Entity.name : "";
            var valid = inscription.validated ? "Válido" : "No válido";

            data.push([college, code, name, surname, email, valid]);
          }

          var buffer = xlsx.build([
            {
              name: inscriptions[0].event.name.substr(0, 31),
              data: data,
            },
          ]);

          var fileName = cdnHelper.sanitizeFilename(inscriptions[0].event.name + "-inscripciones.xlsx");
          var xlsxPath = cdnHelper.getCDNPath("xlsx") + fileName;
          var wstream = fs.createWriteStream(xlsxPath);
          wstream.write(buffer);
          wstream.end();

          wstream.on("close", function () {
            return callback(
              {
                messenger: {
                  success: true,
                  message: "Ok",
                  code: "S99001",
                },
                data: {
                  path: xlsxPath,
                  name: fileName,
                },
              },
              200
            );
          });
        } else {
          return callback(
            {
              messenger: {
                success: true,
                message: "Ok",
                code: "S99002",
              },
            },
            200
          );
        }
      })
      .catch(function (error) {
        console.log(error);
        return callback(
          {
            messenger: {
              success: false,
              message: "Database error getting inscription.",
              code: "E01004",
            },
          },
          500
        );
      });
  },
};

module.exports = generateService(models.EventInscription, extraMethods);
