const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const Subscription = mongoose.model('subscribers');
// const q = require('q');
const webpush = require('web-push');

const tools = require('../tools/general');

const { authenticate } = require('../middleware/authenticate');

const shared_consts = require('../tools/shared_nodejs');
const server_constants = require('../tools/server_constants');

const { User } = require('../models/user');

router.post('/', (req, res) => {
  const payload = {
    title: req.body.title,
    message: req.body.message,
    url: req.body.url,
    ttl: req.body.ttl,
    icon: req.body.icon,
    image: req.body.image,
    badge: req.body.badge,
    tag: req.body.tag
  };

  Subscription.find({}, (err, subscriptions) => {
    if (err) {
      console.error(`Error occurred while getting subscriptions`);
      res.status(500).json({
        error: 'Technical error occurred'
      });

    } else {
      let parallelSubscriptionCalls = subscriptions.map((subscription) => {
        return new Promise((resolve, reject) => {
          const pushSubscription = {
            endpoint: subscription.endpoint,
            keys: {
              p256dh: subscription.keys.p256dh,
              auth: subscription.keys.auth
            }
          };

          const pushPayload = JSON.stringify(payload);
          const pushOptions = {
            vapidDetails: {
              subject: process.env.URLBASE_APP1,
              privateKey: process.env.PRIVATE_VAPI_KEY,
              publicKey: process.env.PUBLIC_VAPI_KEY,
            },
            TTL: payload.ttl,
            headers: {}
          };
          webpush.sendNotification(
            pushSubscription,
            pushPayload,
            pushOptions
          ).then((value) => {
            resolve({
              status: true,
              endpoint: subscription.endpoint,
              data: value
            });
          }).catch((err) => {
            reject({
              status: false,
              endpoint: subscription.endpoint,
              data: err
            });
          });
        });
      });
      q.allSettled(parallelSubscriptionCalls).then((pushResults) => {
        console.info(pushResults);
      });
      res.json({
        data: 'Push triggered'
      });
    }
  });
});

async function SendMsgTo(idapp, username, params) {

  return await User.find({ idapp, username }).then((arrusers) => {
    if (arrusers !== null) {
      for (const user of arrusers) {
        tools.sendNotificationToUser(user._id, params.title, params.content, params.openUrl, params.openUrl2, params.tag, params.actions)
          .then(ris => {
            if (ris) {

            } else {
              // already sent the error on calling sendNotificationToUser
            }
          })
          .catch(e => {
            console.error(e.message);
          })
      }
    }
  });

}

async function SendMsgToAll(idapp, params) {
  const arrusers = await User.find({ idapp },
    {
      username: 1,
      name: 1,
      surname: 1,
    }
  );

  let msgsent = 0;

  for (const user of arrusers) {
    await SendMsgTo(idapp, user.username, params);
    msgsent++;
  }

  return msgsent;
}

router.post('/send', authenticate, async (req, res) => {
  const idapp = req.body.idapp;
  const params = req.body.params;

  let nummsg = 0;

  if ((!User.isAdmin(req.user.perm) && !User.isManager(req.user.perm) && !User.isTutor(req.user.perm))) {
    // If without permissions, exit
    return res.status(404).send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: '' });
  }

  try {
    if (params.typemsg === shared_consts.TypeMsg.SEND_TO_ALL) {
      nummsg = await SendMsgToAll(idapp, params);
    }

    return res.send({ code: server_constants.RIS_CODE_OK, msg: nummsg + ' Msg Inviati !' });
  }catch (e) {
    return res.send({ code: server_constants.RIS_CODE_ERR, msg: nummsg + ' Msg Inviati !' });
  }

});

router.get('/', (req, res) => {
  res.json({
    data: 'Invalid Request Bad'
  });
});
module.exports = router;
