/* global Events Reservations */
"use strict";

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

function getWhereTypeEntity(entityType) {
  var whereType = {};
  if (entityType == "partners") whereType = { alias: "partner" };
  else if (entityType == "colleges") whereType = { alias: "college" };
  return whereType;
}

const extraMethods = {
  async beforeCreate(values, context){
    //En el caso de ser una reserva publicada debe descontar del aforo del evento asociado
    if (values.state === 'publish') {
      await eventService._updateAforoOfEventReservation(values, values.assistants);
    };
    return values;
  },
  
  _getReservaById: (Id) => {
    return models.EventReservation.findOne({
      where: { id: Id },
    });
  },

  _getReservaByIdWithEntityAndEvent: (Id) => {
    return models.EventReservation.findOne({
      where: { id: Id },
      include: [{ model: models.Event }, { model: models.Entity }],
    });
  },

  _getReservasByEventAndEntity: (eventId, entityId) => {
    return models.EventReservation.findAll({
      where: { eventId: eventId, entityId: entityId },
      include: [{ model: models.Event }, { model: models.Entity }],
    });
  },

  _getReservasByEventAndType: (eventId, type) => {
    return models.EventReservation.findAll({
      where: { eventId: eventId },
      include: [
        {
          model: models.Event,
        },
        {
          model: models.Entity,
          include: [{ model: models.EntityType, as: "types", where: getWhereTypeEntity(type) }],
        },
      ],
      order: [["entityId", "asc"]],
    });
  },

  _getReservaByCode: (eventId, code) => {
    return models.EventReservation.findOne({
      where: { reservation_code: code, eventId: eventId },
      include: [
        {
          model: models.Event,
        },
        { model: models.Entity },
      ],
    });
  },

  _getReservaByOnlyCode: (code) => {
    return models.EventReservation.findOne({
      where: { reservation_code: code },
      include: [
        {
          model: models.Event,
        },
        { model: models.Entity },
      ],
    });
  },

  _getPartners: (eventId) => {
    return models.EventReservation.findAll({
      where: { eventId: eventId },
      include: [
        { model: models.Entity, include: [{ model: models.EntityType, as: "types", where: { alias: "partner" } }] },
      ],
      order: [
        [{ model: models.Entity }, "name", "asc"],
        ["description", "desc"],
      ],
    });
  },

  _getColleges: (eventId) => {
    return models.EventReservation.findAll({
      where: { eventId: eventId, virtual: 0 },
      include: [
        {
          model: models.Entity,
          include: [{ model: models.EntityType, as: "types", where: { alias: "college" } }],
        },
      ],
      order: [
        [{ model: models.Entity }, "name", "asc"],
        ["description", "desc"],
      ],
    });
  },

  _updateConfirmedReservation: (id, confirmed) => {
    return new Promise(function (resolve, reject) {
      models.EventReservation.update(
        {
          confirmed: confirmed,
        },
        {
          where: { id: id },
        }
      )
        .then(function (result) {
          resolve(result[0] === 1);
        })
        .catch(function (error) {
          reject(error);
        });
    });
  },

  _updateSoldOutReservation: (id, sold_out) => {
    return new Promise(function (resolve, reject) {
      models.EventReservation.update(
        {
          sold_out: sold_out,
        },
        {
          where: { id: id },
        }
      )
        .then(function (result) {
          resolve(result[0] === 1);
        })
        .catch(function (error) {
          reject(error);
        });
    });
  },

  _updatePublishReservation: (id) => {
    return new Promise(function (resolve, reject) {
      models.EventReservation.update(
        {
          state: "publish",
        },
        {
          where: { id: id },
        }
      )
        .then(function (result) {
          resolve(result[0] === 1);
        })
        .catch(function (error) {
          reject(error);
        });
    });
  },

  _generateReservatioCode: (event, entityName) => {
    let result = "default";
    let entity = entityName ? entityName : "DEFAULT";
    if (!event) return result;

    let xxx = event.location.city.replace(/\s+/g, "").substr(0, 3);
    let yyy = moment(event.init_date).format("YY");
    let zzz = entity.replace(/\s+/g, "").substr(0, 3);
    let www = Math.floor(Math.random() * 999 + 1)
      .toString()
      .padStart(3, "0");
    result = `${xxx}${yyy}-${zzz}${www}`;

    return result.toUpperCase();
  },

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

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

  _getReservationsExcel: (user, eventId, entityId, entityType, callback) => {
    console.log("DESCARGA EXCEL>>>>>>>> ");
    console.log(">>>>>>>>>>>>>>>>>>>><consulta con eventId:", eventId);
    console.log(">>>>>>>>>>>>>>>>>>>><consulta con type:", entityType);
    console.log(">>>>>>>>>>>>>>>>>>>><consulta con entityId:", entityId);

    const where = {
      eventId: eventId
    };

    if (entityId) {
      where['entityId'] = entityId;
    };

    models.EventReservation.findAll({
      where,
      include: [
        {
          model: models.Event,
          attributes: ["id", "name"],
        },
        {
          model: models.Entity,
          include: [{ model: models.EntityType, as: "types", where: getWhereTypeEntity(entityType) }],
        },
        {
          model: models.EventInscription,
          as: "inscriptions",
          required: false,
        },
      ],

      order: [
        [{ model: models.Entity }, "name", "ASC"],
        ["reservation_code", "ASC"],
        [{ model: models.EventInscription, as: "inscriptions" }, "date", "ASC"],
      ],
    })
      .then(function (reservations) {
        if (reservations.length) {
          var data = [];

          data.push(["Congreso: " + reservations[0].Event.name]);
          data.push(["Fecha del listado: " + moment().toString()]);
          data.push([]);
          data.push([
            "Nombre",
            "Apellidos",
            "Email",
            "Válido",
            "Vía",
            "N. entrada",
            "Tipo invitación",
            "Código",
            "Partner",
          ]);

          var currentReservation = "";
          var currentPartner = "";
          reservations.forEach(function (reserva) {
            if (currentPartner != reserva.Entity.name) {
              currentPartner = reserva.Entity.name;
              //                        data.push([]);
              //                        data.push([]);
            }

            if (currentReservation != reserva.reservation_code) {
              currentReservation = reserva.reservation_code;
              //                        data.push([]);
              //                        data.push(["Partner: " + reserva.Entity.name + "  CÓDIGO: " + reserva.reservation_code, "Tipo: " + reserva.description, "Reservadas: " + reserva.confirmed, "Aforo: " + reserva.assistants]);
              //
              //                        data.push(["Nombre", "Apellidos", "Email", "Válido", "Vía", "N. entrada"]);
            }

            reserva.inscriptions.forEach(function (inscription) {
              data.push([
                inscription.user.name,
                inscription.user.surname,
                inscription.user.email,
                inscription.validated ? "Confirmado" : "En lista de espera",
                inscription.source,
                inscription.code_ticket,
                reserva.description,
                reserva.reservation_code,
                reserva.Entity.name,
              ]);
            });
          });

          var buffer = xlsx.build(
            [
              {
                name: reservations[0].Event.name.substr(0, 31),
                data: data,
              },
            ],
            {
              "!cols": [{ wch: 15 }, { wch: 25 }, { wch: 30 }, { wch: 10 }, { wch: 20 }, { wch: 20 }, { wch: 5 }],
            }
          );

          var fileName = cdnHelper.sanitizeFilename(reservations[0].Event.name + "-invitaciones.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 invitations.",
              code: "E01004",
            },
          },
          500
        );
      });
  },
};

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