"use strict";
const httpStatus = require("http-status");
const moment = require("moment");
const generateControllers = require("../../core/controllers");
const { buildContext } = require("../../core/controllers");
const notificationService = require("./notification.service");
const notificationDetailService = require("./notification_detail.service");
const userService = require("../auth/user.service");
const userDeviceService = require("./user_device.service");
const eventInscriptionService = require("../events/events_inscriptions.service");
const { usersIdsComposer } = require("../../helpers/composes.helper");
const pushHelper = require("../../helpers/push.helper");
const notificationHelper = require("../../helpers/notification.helpers");

const {
  extractParamsFromRequest,
  handleErrorResponse,
  handleResultResponse,
} = require("../../helpers/controller.helper");
const { get } = require("lodash");

// Module Name
const MODULE_NAME = "[notification.controller]";
const controllerOptions = { MODULE_NAME };

async function _sendNotificationAllActiveUsers(notification) {
  let limit = 33;
  let page = 1;

  let totalRows = 0;
  let totalPages = -1;

  do {
    let offset = (page - 1) * limit;
    let result = await userService._getActiveUserIds(offset, limit, notification.recipients.country);

    if (totalPages == -1) {
      totalPages = Math.ceil(result.count / limit);
    }

    page = page + 1;

    let ids = result.rows.map(function (item) {
      return item.id;
    });
    notificationService.sendNotificationToUsers(notification, ids);
  } while (page <= totalPages);

  return "OK";
}

async function _sendNotificationAllActiveDevices(notification) {
  let limit = 33;
  let page = 1;

  let totalRows = 0;
  let totalPages = -1;

  do {
    let offset = (page - 1) * limit;
    let result = await userDeviceService._getActiveDeviceIds(offset, limit, notification.recipients.country);

    console.log(result);

    if (totalPages == -1) {
      totalPages = Math.ceil(result.count / limit);
    }

    page = page + 1;

    notificationService.sendNotificationToDevices(notification, result.rows);
  } while (page <= totalPages);

  return "OK";
}

async function _getUserIdsForEventId(eventId, segment) {
  let userIds = [];

  switch (segment) {
    //Todos los inscritos tanto invitados como libres
    case "ALL_VALIDATED":
      userIds = await eventInscriptionService._getInscriptionByEventAndValidated(eventId, true);
      break;
    //Todos los de lista de espera tanto invitados como libres (Actualmente en invitados no hay lista de espera)
    case "ALL_NOT_VALIDATED":
      userIds = await eventInscriptionService._getInscriptionByEventAndValidated(eventId, false);
      break;

    //Solo invitados como actualmente no se usa codigo de reserva para los coles, vale con filtrar por aquellos que tengan codigo de reserva
    case "PARTNERS_ALL":
      userIds = await eventInscriptionService._getInscriptionByEventFromPartner(eventId);
      break;

    //Todos los inscritos al evento, tanto validados como en lista de espera
    default: //ALL
      userIds = await eventInscriptionService._getInscriptionByEvent(eventId);
      break;
  }

  return usersIdsComposer(userIds);
}

const extraControllers = {
  sendNotification: (config) => {
    /**
     * notificationSample = {
     *  "title": "título de la notificación",
     *  "body": "cuerpo de la notificación",
     *  "recipients": {
     * OPCION 1- Unos usuarios determinados
     *      "userIds": ["*" | "f428a317-6d1f-4eda-aa3e-22baff3f48d7", ...]
     *      "segment": "ALL" | "LAST_YEAR" | "LAST_MONTH"
     *      "country": "*" | "ES" | "MX"
     *
     * OPCION 2 - A todos los usuarios inscritos a un evento, se puede segmentar
     *      "eventId": "xxx-xxx-xxx-xxx",
     *      "segment": "ALL" | "ALL_VALIDATED" | "ALL_NOT_VALIDATED" |
     *                 "PARTNERS_ALL" | "PARTNERS_VALIDATED" | "PARTNERS_NOT_VALIDATED" |
     *                 "COLLEGE_ALL" | "COLLEGE_VALIDATED" | "COLLEGE_NOT_VALIDATED"
     * OPCION 3 - A todos los dispositivos activos de un país
     *      "deviceIds": ["*" | "ExponentPushToken[YbOS1AIZjQbchZbxNaVRqC]", ...]
     *      "country": "*" | "ES" | "MX"
     *  },
     * "data": {
     *      "type": "message",
     *      "title": "Título del mensaje",
     *      "message": "Cuerpo del mensaje",
     *      "button": {
     *          "caption": "Etiqueta del boton",
     *               "url": "https://www.site.es",
     *               "screen": "<RouterName>",
     *               "paramId": "23",
     *      }
     * }
     *}
     */

    return async (req, res, next) => {
      config = config || {
        scopes: [],
      };

      const context = buildContext(req, config);
      let params = extractParamsFromRequest(req, res);

      let receipt = undefined;
      let userIds = undefined;
      let deviceIds = undefined;
      let eventId = undefined;
      let segment = undefined;
      let country = undefined;

      const { body } = req;

      if (!body.title) {
        return handleErrorResponse(
          controllerOptions.MODULE_NAME,
          "sendNotification",
          new Error("Missing message title"),
          res
        );
      }

      if (!body.body) {
        return handleErrorResponse(
          controllerOptions.MODULE_NAME,
          "sendNotification",
          new Error("Missing body content"),
          res
        );
      }

      // Evento?
      if (body.recipients.eventId) {
        eventId = body.recipients.eventId;
        segment = body.recipients.segment;
      } else if (body.recipients.userIds) {
        userIds = body.recipients.userIds;
        segment = body.recipients.segment;
        country = body.recipients.country;
      } else if (body.recipients.deviceIds) {
        deviceIds = body.recipients.deviceIds;
        country = body.recipients.country;
      } else {
        return handleErrorResponse(
          controllerOptions.MODULE_NAME,
          "sendNotification",
          new Error("Missing user Ids or event Ids or devices Ids"),
          res
        );
      }

      try {
        let notification = notificationHelper.createNotification({
          ...body,
          userId: context.user.id,
        });

        if (userIds && userIds.length == 1 && userIds[0] == "*") {
          receipt = _sendNotificationAllActiveUsers(notification);
        } else if (deviceIds && deviceIds.length == 1 && deviceIds[0] == "*") {
          receipt = _sendNotificationAllActiveDevices(notification);
        } else {
          let _userIds = null;

          if (userIds) {
            _userIds = userIds;
          } else {
            if (eventId) {
              _userIds = await _getUserIdsForEventId(eventId, segment);
            } else {
              return handleErrorResponse(
                controllerOptions.MODULE_NAME,
                "sendNotification",
                new Error("Missing event and segment"),
                res
              );
            }
          }

          if (_userIds) {
            receipt = notificationService.sendNotificationToUsers(notification, _userIds);
          }
        }

        return handleResultResponse(receipt, null, null, res, httpStatus.OK);
      } catch (error) {
        console.error(error);
        return handleErrorResponse(controllerOptions.MODULE_NAME, "sendNotification", error, res);
      }
    };
  },

  updateNotificationsWithReceipts: (config) => {
    return async (req, res, next) => {
      /*config = config || {
                scopes: [],
            };

            const context = buildContext(req, config);
            let params = extractParamsFromRequest(req, res);

            let getNotificationsWithoutReceipt = async () => {
                let params = {
                    where: {}
                };
                return await notificationDetailService.fetchAll(params, context);
            }

            let receipt = await Promise.all(getUserDevicesList).then(
                function (userDeviceList) {
                    return Promise.all(userDeviceList.map(buildMessagePromise))
                })
                .then(sendNotificationsPromise)
            */
    };
  },

  registerDevice: (config) => {
    return async (req, res, next) => {
      config = config || {
        scopes: [],
      };

      try {
        const context = buildContext(req, config);
        const userId = context.user && context.user.id ? context.user.id : null;

        let data = {
          token: req.body.token,
          valid: 1,
          country: req.body.country,
          userId,
        };

        let params = extractParamsFromRequest(req, res, {
          includeAll: false,
          paginate: { limit: 1, page: 1 },
          params: {
            token: data.token,
          },
        });

        console.log(req.body, data, params);

        // Buscamos el token y el usuario
        console.log(">> Busco el token", params.params);
        let result = await userDeviceService.fetchOne(params, context);

        if (result) {
          // Borramos el registro donde aparece el token
          console.log(">> Borro el registro del token", params.params, data, context);
          result = await userDeviceService.delete(params, context);
        }

        // Dar de alta el token
        console.log(">> Dar de alta el token", data);
        result = await userDeviceService.create(data, context);
      } catch (error) {
        console.error(error);
      }
      // En todo caso devolver OK al cliente
      return handleResultResponse("OK", null, null, res, httpStatus.OK);
    };
  },
};

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