const mongoose = require('mongoose').set('debug', false);
const Schema = mongoose.Schema;

mongoose.Promise = global.Promise;
mongoose.level = 'F';

const i18n = require('i18n');

const { ObjectId } = require('mongodb');

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

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

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

// Resolving error Unknown modifier: $pushAll
mongoose.plugin((schema) => {
  schema.options.usePushEach = true;
});

const sendNotifSchema = new Schema({
  idapp: {
    type: String,
    index: true,
  },
  typedir: {
    type: Number,
    default: 0,
    index: true,
  },
  typeid: {
    type: Number,
    default: 0,
    index: true,
  },
  sender: {
    // mittente
    type: String,
    default: '',
    index: true,
  },
  dest: {
    type: String,
    default: '',
  },
  descr: {
    type: String,
  },
  sendergroup: {
    // mittente
    type: String,
    default: '',
  },
  destgroup: {
    type: String,
    default: '',
  },
  title: {
    type: String,
  },
  openUrl: {
    type: String,
  },
  datenotif: {
    type: Date,
  },
  date_created: {
    type: Date,
    default: Date.now,
  },
  status: {
    type: Number,
    default: 0,
    index: true,
  },
  typesend: {
    type: Number,
  },
  read: {
    type: Boolean,
    default: false,
  },
  tablerec: {
    type: String,
  },
  idrec: {
    type: String,
  },
  deleted: {
    type: Boolean,
    default: false,
  },
  extrafield: {
    type: String,
  },
  extrarec: {
    type: Object,
  },
  tag: {
    type: String,
  },
  options: {
    type: Array,
  },
  textaddTelegram: {
    type: String,
  },
  textcontent_Telegram: {
    type: String,
  },
  linkaddTelegram: {
    type: String,
  },
  img: {
    type: String,
  },
  inviaaListaUtenti: {
    type: Boolean,
  }
});

/*sendNotifSchema.index({ idapp: 1 });
sendNotifSchema.index({ typedir: 1 });
sendNotifSchema.index({ typeid: 1 });
sendNotifSchema.index({ sender: 1 });*/

sendNotifSchema.index({ idapp: 1, typedir: 1, typeid: 1, status: 1, sender: 1 });

sendNotifSchema.statics.setNotifAsRead = async function (idapp, username, idnotif) {
  const SendNotif = this;

  if (!username) return null;

  try {
    if (idnotif) {
      return await SendNotif.findOneAndUpdate(
        {
          $and: [{ idapp }, { dest: username }, { _id: idnotif }],
          $or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
        },
        { $set: { read: true } },
        { new: false }
      )
        .then((ret) => {
          return !!ret;
        })
        .catch((err) => {
          console.error('err', err);
        });
    }
  } catch (e) {
    return false;
  }
};

sendNotifSchema.statics.getRecNotif = async function (id) {
  const SendNotif = this;

  try {
    return await SendNotif.findById(id).lean();
  } catch (e) {
    return null;
  }
};

sendNotifSchema.statics.findAllNotifByUsernameIdAndIdApp = function (
  username,
  lastdataread,
  idapp,
  limitrecord,
  qualinotif,
  arroptionfilter
) {
  const SendNotif = this;

  if (!lastdataread) lastdataread = 0;

  let arrfilter = [{ idapp }, { dest: username }, { datenotif: { $gt: new Date(lastdataread) } }];

  if (qualinotif) {
    if (qualinotif === shared_consts.QualiNotifs.CIRCUITS) {
      arrfilter.push({ typedir: shared_consts.TypeNotifs.TYPEDIR_CIRCUITS });
    } else {
      arrfilter.push({ typedir: { $ne: shared_consts.TypeNotifs.TYPEDIR_CIRCUITS } });
    }
  }

  if (arroptionfilter) {
    arrfilter = [...arrfilter, ...arroptionfilter];
  }

  return SendNotif.find({
    $and: arrfilter,
  })
    .lean()
    .limit(limitrecord)
    .sort({ datenotif: -1 })
    .then(async (arrnotif) => {
      // console.log('arrnotif', arrnotif.length);

      return this.compileOtherFields(arrnotif);
    })
    .catch((err) => {
      console.error('err', err);
    });
};

sendNotifSchema.statics.getDescrAndLinkByRecNotif = async function (recnotif, userorig) {
  const numchars = 80;
  let newdescr = '';
  let newdescrtelegram = '';
  let mydescr = '';
  let myidrec = '';
  let sender = recnotif.sender ? recnotif.sender : '';
  let tag = '';

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

  try {
    let dovestr = '';
    if (recnotif.myrectableorig) {
      myidrec = recnotif.myrectableorig._id;
      mydescr = recnotif.myrectableorig.descr ? tools.firstchars(recnotif.myrectableorig.descr, numchars) : '';
      dovestr = tools.getDoveStrByAnnuncio(recnotif.myrectableorig);
    }

    if (recnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_BACHECA) {
      let tablerec = '';
      if (recnotif.typeid === shared_consts.TypeNotifs.ID_BACHECA_NEW_GOOD) {
        newdescr = i18n.__('NEW_GOOD', userorig, mydescr, dovestr);
        recnotif.openUrl = shared_consts.getDirectoryByTable(shared_consts.TABLES_MYGOODS, true) + myidrec;
        tag = 'newgood';
        tablerec = 'mygoods';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_BACHECA_NEW_SERVICE) {
        newdescr = i18n.__('NEW_SERVICE', userorig, mydescr, dovestr);
        recnotif.openUrl = shared_consts.getDirectoryByTable(shared_consts.TABLES_MYSKILLS, true) + myidrec;
        tag = 'newservice';
        tablerec = 'myskills';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_BACHECA_NEW_HOSP) {
        newdescr = i18n.__('NEW_HOSP', userorig, mydescr, dovestr);
        recnotif.openUrl = shared_consts.getDirectoryByTable(shared_consts.TABLES_MYHOSPS, true) + myidrec;
        tag = 'newhosp';
        tablerec = 'myhosps';
      }
      if (recnotif.myrectableorig) {
        let eventobj = await tools.getAnnuncioForTelegram(recnotif.myrectableorig, tablerec, mydescr, userorig, true);
        recnotif.textcontent_Telegram = eventobj.newdescrtelegram;
      } else {
        recnotif.textcontent_Telegram = newdescr;
      }
      recnotif.linkaddTelegram = '';
    } else if (recnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_EVENTS) {
      recnotif.openUrl = shared_consts.getDirectoryByTable(shared_consts.TABLES_MYBACHECAS, true) + myidrec;
      tag = 'newevent';
      if (recnotif.typeid === shared_consts.TypeNotifs.ID_EVENTS_NEW_REC) {
        // let eventobj = await tools.getEventForTelegram(recnotif.myrectableorig, mydescr, userorig);
        let eventobj = await tools.getAnnuncioForTelegram(
          recnotif.myrectableorig,
          shared_consts.TABLES_MYBACHECAS,
          mydescr,
          userorig,
          true
        );
        newdescr = eventobj.descrperNotif;
        newdescrtelegram = eventobj.newdescrtelegram;
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_EVENTS_SEND_MSG) {
        newdescr = i18n.__('EVENT_SEND_MSG', userorig, recnotif.title, recnotif.msg);
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_EVENTS_ATTEND) {
        // ++ Controlla se esiste già
        let esitegia = recnotif.paramsObj.recObjCreator.exist; // ++

        if (esitegia)
          newdescr = i18n.__(
            'SET_ATTEND_OTHERS',
            recnotif.paramsObj.username_action,
            recnotif.paramsObj.recObjCreator.numattend - 1,
            recnotif.paramsObj.recObjCreator.descr
          );
        else
          newdescr = i18n.__('SET_ATTEND', recnotif.paramsObj.username_action, recnotif.paramsObj.recObjCreator.descr);

        recnotif.openUrl =
          shared_consts.getDirectoryByTable(recnotif.paramsObj.recObjCreator.table, true) +
          recnotif.paramsObj.recObjCreator.id;
        tag = 'attend';
      }
      recnotif.textcontent_Telegram = newdescrtelegram;
      // recnotif.linkaddTelegram = i18n.__('SHOW_POST');
    } else if (recnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_FRIENDS) {
      recnotif.openUrl = '/my/' + sender;
      if (recnotif.typeid === shared_consts.TypeNotifs.ID_FRIENDS_NEW_REC) {
        newdescr = i18n.__('<strong>%s</strong> asked you for Friendship', sender, mydescr);
        tag = 'newfriend';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_FRIENDS_ACCEPTED) {
        newdescr = i18n.__('<strong>%s</strong> accepted your Friendship', sender, mydescr);
        tag = 'acceptedfriend';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_FRIENDS_ACCEPTED_MY_REQUEST) {
        newdescr = i18n.__("✅ You have accepted %s' Friendship request!", sender, mydescr);
        tag = 'acceptedfriend';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_FRIENDS_REFUSED) {
        newdescr = i18n.__('<strong>%s</strong> refused your Friendship', sender, mydescr);
        tag = 'refusedfriend';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_FRIENDS_REPORTED) {
        tag = 'reportuser';
        if (recnotif.paramsObj.usernameDest === recnotif.paramsObj.username_action) {
          newdescr = i18n.__('FRIEND_REPORTED_YOU', recnotif.paramsObj.username_worked);
          recnotif.openUrl = '/my/' + recnotif.paramsObj.username_worked;
        } else if (recnotif.paramsObj.isAdmin) {
          newdescr = i18n.__('FRIEND_REPORTED', recnotif.paramsObj.usernameDest, sender);
          recnotif.openUrl = '/my/' + recnotif.paramsObj.usernameDest;
        } else {
          recnotif.openUrl = '/my/' + recnotif.paramsObj.username_action;
          newdescr = i18n.__(
            'FRIEND_REPORTED_TO_ME',
            recnotif.paramsObj.username_action,
            recnotif.paramsObj.username_action
          );
        }
      }
    } else if (recnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_HANDSHAKE) {
      recnotif.openUrl = '/my/' + sender;
      if (recnotif.typeid === shared_consts.TypeNotifs.ID_HANDSHAKE_ACCEPTED) {
        newdescr = i18n.__('HANDSHAKE_SET', sender, mydescr);
        tag = 'acceptedhandshake';
      }
    } else if (recnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_GROUPS) {
      tag = 'group';
      recnotif.openUrl = shared_consts.getDirectoryByTable('mygroups', true) + recnotif.paramsObj.groupnameDest;
      if (recnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_NEW_REC) {
        newdescr = i18n.__('GROUP_CREATED', sender, recnotif.paramsObj.groupnameDest);
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_ACCEPTED) {
        if (recnotif.paramsObj.isAdmin) {
          newdescr = i18n.__(
            'ACCETTATO_NOTIFICA_ADMINS',
            sender,
            recnotif.paramsObj.groupnameDest,
            recnotif.paramsObj.username_action
          );
          recnotif.openUrl = '/my/' + sender;
        } else {
          newdescr = i18n.__('GROUPS_ACCEPTED', recnotif.paramsObj.groupnameDest, recnotif.paramsObj.username_action);
        }
        tag = 'addgroup';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_REMOVED) {
        if (
          recnotif.paramsObj.username_action === recnotif.paramsObj.usernameDest &&
          sender === recnotif.paramsObj.usernameDest
        ) {
          newdescr = i18n.__(
            'GROUPS_EXIT_USER_TO_ME',
            recnotif.paramsObj.groupnameDest,
            recnotif.paramsObj.username_action
          );
        } else if (sender === recnotif.paramsObj.usernameDest) {
          newdescr = i18n.__(
            'GROUPS_REMOVED_TO_ME',
            recnotif.paramsObj.groupnameDest,
            recnotif.paramsObj.username_action
          );
        } else if (sender === recnotif.paramsObj.username_action) {
          newdescr = i18n.__('GROUPS_EXIT_USER', sender, recnotif.paramsObj.groupnameDest);
          recnotif.openUrl = '/my/' + sender;
        } else {
          newdescr = i18n.__(
            'GROUPS_REMOVED',
            sender,
            recnotif.paramsObj.groupnameDest,
            recnotif.paramsObj.username_action
          );
        }

        tag = 'remgroup';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_REFUSED) {
        newdescr = i18n.__(
          'GROUPS_REFUSED',
          sender,
          recnotif.paramsObj.groupnameDest,
          recnotif.paramsObj.username_action
        );
        tag = 'refgroup';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_REQUEST_TO_ENTER) {
        newdescr = i18n.__(
          'GROUP_REQUEST_TO_ENTER',
          sender,
          recnotif.paramsObj.groupnameDest,
          recnotif.paramsObj.singleadmin_username
        );
        tag = 'reqgroups';
        // sendnotifPush = false;  // non lo rimandare 2 volte !
        // telegrambot.askConfirmationUser(idapp, shared_consts.CallFunz.RICHIESTA_GRUPPO, myuser, singleadmin.username, groupname, group._id);
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_BLOCK_USER) {
        newdescr = i18n.__(
          'RICHIESTA_BLOCCO_GRUPPO',
          sender,
          recnotif.paramsObj.groupnameDest,
          recnotif.paramsObj.singleadmin_username
        );
        tag = 'blockgroups';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_DELETE_USER) {
        newdescr = i18n.__('GRUPPO_ELIMINATO', sender, recnotif.paramsObj.username_action);
        tag = 'deletegroup';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_ADDED_ADMIN_OFMYGROUP) {
        if (sender === recnotif.paramsObj.usernameDest) {
          newdescr = i18n.__(
            'GROUPS_ADDED_ADMIN_GROUP_YOU',
            recnotif.paramsObj.groupnameDest,
            recnotif.paramsObj.username_action
          );
        } else {
          newdescr = i18n.__(
            'GROUPS_ADDED_ADMIN_GROUP',
            sender,
            recnotif.paramsObj.groupnameDest,
            recnotif.paramsObj.username_action
          );
          recnotif.openUrl = '/my/' + sender;
        }
        tag = 'addadmingrp';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_REMOVED_ADMIN_OFMYGROUP) {
        if (sender === recnotif.paramsObj.usernameDest) {
          newdescr = i18n.__(
            'GROUPS_REMOVED_ADMIN_GROUP_YOU',
            recnotif.paramsObj.groupnameDest,
            recnotif.paramsObj.username_action
          );
        } else {
          newdescr = i18n.__(
            'GROUPS_REMOVED_ADMIN_GROUP',
            sender,
            recnotif.paramsObj.groupnameDest,
            recnotif.paramsObj.username_action
          );
          recnotif.openUrl = '/my/' + sender;
        }
        tag = 'removeadmingrp';
      }
    } else if (recnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_CIRCUITS) {
      tag = 'circuit';
      let strtipocontoDest = '';
      let strtipocontoOrig = '';
      let groupOComorig = '';
      let groupOComdest = '';
      recnotif.openUrl =
        shared_consts.getDirectoryByTable(shared_consts.TAB_MYCIRCUITS, true) + recnotif.paramsObj.path;
      if (recnotif.paramsObj.extrarec) {
        strtipocontoOrig = recnotif.paramsObj.extrarec.contoComOrig ? i18n.__('COMUNITARIO') : i18n.__('COLLETTIVO');
        strtipocontoDest = recnotif.paramsObj.extrarec.contoComDest ? i18n.__('COMUNITARIO') : i18n.__('COLLETTIVO');
        groupOComorig = recnotif.paramsObj.extrarec.contoComOrig
          ? recnotif.paramsObj.extrarec.contoComOrig
          : recnotif.paramsObj.extrarec.grouporig;
        groupOComdest = recnotif.paramsObj.extrarec.contoComDest
          ? recnotif.paramsObj.extrarec.contoComDest
          : recnotif.paramsObj.extrarec.groupdest;
      }
      let myorig = '';
      let mydest = '';
      let destinatario = '';
      let qty = '';
      let symbol = '';
      let username_action = '';
      let username_mittente = '';
      let circuitname = '';
      let numuserincircuit = 0;
      try {
        circuitname = recnotif.paramsObj.circuitnameDest;
        username_action = recnotif.paramsObj.username_action;
        username_mittente = recnotif.paramsObj.sender ? recnotif.paramsObj.sender : username_action;
        myorig = recnotif.paramsObj.extrarec.grouporig;
        mydest = recnotif.paramsObj.extrarec.groupdest
          ? recnotif.paramsObj.extrarec.groupdest
          : recnotif.paramsObj.extrarec.dest;
        destinatario = recnotif.paramsObj.extrarec.dest
          ? recnotif.paramsObj.extrarec.dest
          : recnotif.paramsObj.extrarec.groupdest
          ? recnotif.paramsObj.extrarec.groupdest
          : recnotif.paramsObj.extrarec.contoComDest;
        qty =
          recnotif.paramsObj.extrarec && recnotif.paramsObj.extrarec.qty
            ? recnotif.paramsObj.extrarec.qty.toString()
            : '';
        symbol = recnotif.paramsObj.extrarec ? recnotif.paramsObj.extrarec.symbol : '';
        numuserincircuit = await User.countUsersInCircuit(recnotif.idapp, circuitname);
      } catch (e) {}

      recnotif.textaddTelegram = '';

      if (groupOComdest) {
        destinatario += ' (' + username_mittente + ')';
      }

      const circuit = await Circuit.findOne({ name: circuitname });

      if (recnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_NEW_REC) {
        newdescr = i18n.__('CIRCUIT_CREATED', sender, recnotif.paramsObj.circuitnameDest);
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_SETFIDO) {
        if (recnotif.paramsObj.isAdmin) {
          if (recnotif.extrarec.groupname) {
            newdescr = i18n.__(
              'FIDO_IMPOSTATO_ADMINS_CIRCUIT_MYGROUP',
              recnotif.extrarec.groupname,
              -recnotif.paramsObj.extrarec.fidoConcesso,
              recnotif.paramsObj.circuitnameDest,
              username_action
            );
            tag = 'setfido_admin_group';
          } else {
            newdescr = i18n.__(
              'FIDO_IMPOSTATO_ADMINS_CIRCUIT',
              sender,
              -recnotif.paramsObj.extrarec.fidoConcesso,
              recnotif.paramsObj.circuitnameDest,
              username_action
            );
            tag = 'setfido_admin';
          }

          recnotif.openUrl = '/my/' + sender;
        } else {
          newdescr = i18n.__(
            'FIDO_IMPOSTATO',
            recnotif.paramsObj.circuitnameDest,
            recnotif.paramsObj.extrarec.username_admin_abilitante,
            -recnotif.paramsObj.extrarec.fidoConcesso,
          );
          tag = 'setfido';
        }
        
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_ACCEPTED) {
        if (recnotif.paramsObj.isAdmin) {
          if (recnotif.extrarec.groupname) {
            newdescr = i18n.__(
              'ACCETTATO_NOTIFICA_ADMINS_CIRCUIT_MYGROUP',
              recnotif.extrarec.groupname,
              recnotif.paramsObj.circuitnameDest,
              username_action
            );
          } else {
            newdescr = i18n.__(
              'ACCETTATO_NOTIFICA_ADMINS_CIRCUIT',
              sender,
              recnotif.paramsObj.circuitnameDest,
              username_action
            );
          }

          recnotif.openUrl = '/my/' + sender;
        } else {
          if (sender === recnotif.paramsObj.usernameDest) {
            newdescr = i18n.__(
              'CIRCUIT_ACCEPTED',
              username_action,
              recnotif.paramsObj.circuitnameDest,
              tools.getHostByIdApp(recnotif.idapp) + recnotif.openUrl
            );
          } else {
            newdescr = i18n.__(
              'CIRCUIT_ACCEPTED_YOU',
              recnotif.paramsObj.usernameDest,
              recnotif.paramsObj.circuitnameDest
            );
          }
        }
        tag = 'addcircuit';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_REMOVED) {
        if (username_action === recnotif.paramsObj.usernameDest && sender === recnotif.paramsObj.usernameDest) {
          newdescr = i18n.__('CIRCUIT_EXIT_USER_TO_ME', recnotif.paramsObj.circuitnameDest, username_action);
        } else if (sender === recnotif.paramsObj.usernameDest) {
          newdescr = i18n.__('CIRCUIT_REMOVED_TO_ME', recnotif.paramsObj.circuitnameDest, username_action);
        } else if (sender === username_action) {
          newdescr = i18n.__('CIRCUIT_EXIT_USER', sender, recnotif.paramsObj.circuitnameDest);
          recnotif.openUrl = '/my/' + sender;
        } else {
          newdescr = i18n.__('CIRCUIT_REMOVED', sender, recnotif.paramsObj.circuitnameDest, username_action);
        }

        tag = 'remcircuit';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_REFUSED) {
        if (recnotif.paramsObj.isAdmin) {
          if (recnotif.extrarec.groupname) {
            newdescr = i18n.__(
              'CIRCUIT_REFUSED_TO_MYGROUP',
              recnotif.extrarec.groupname,
              recnotif.paramsObj.circuitnameDest,
              username_action
            );
          }
        } else {
          newdescr = i18n.__('CIRCUIT_REFUSED', username_action, recnotif.paramsObj.circuitnameDest);
        }
        tag = 'refcircuit';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_REQUEST_TO_ENTER) {
        aportador_solidario = await User.getAportadorSolidarioByUsername(recnotif.idapp, sender);
        if (recnotif.extrarec.groupname) {
          newdescr = i18n.__(
            'CIRCUIT_REQUEST_TO_ENTER_WITH_GROUP',
            recnotif.extrarec.groupname,
            recnotif.paramsObj.circuitnameDest,
            numuserincircuit,
            recnotif.paramsObj.singleadmin_username
          );
        } else {
          newdescr = i18n.__(
            'CIRCUIT_REQUEST_TO_ENTER',
            sender,
            '<strong>' + recnotif.paramsObj.circuitnameDest + '</strong>',
            numuserincircuit,
            aportador_solidario
          );

          if (circuit.askManagerToEnter)
            newdescr = i18n.__(
              'CIRCUIT_REQUEST_TO_ENTER_ASKMANAGER',
              sender,
              '<strong>' + recnotif.paramsObj.circuitnameDest + '</strong>',
              numuserincircuit,
              aportador_solidario
            );
        }

        const myadmins = await Circuit.getListAdmins(recnotif.idapp, recnotif.paramsObj.circuitnameDest);
        recnotif.textaddTelegram += '\n' + i18n.__('CIRCUIT_ADMINS', myadmins.num, myadmins.str);
        recnotif.textaddTelegram +=
          '\n' +
          i18n.__(
            'CIRCUIT_WHERE_IS_PRESENT',
            await Circuit.getListCircuitsByUsername(recnotif.idapp, sender, recnotif.extrarec.groupname)
          );

        tag = 'reqcircuits';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_DELETE_USER) {
        newdescr = i18n.__('CIRCUIT_ELIMINATO', sender, username_action);
        tag = 'deletecircuit';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_ADDED_ADMIN) {
        if (sender === recnotif.paramsObj.usernameDest) {
          newdescr = i18n.__(
            'CIRCUIT_ADDED_ADMIN_YOU',
            recnotif.paramsObj.usernameDest,
            recnotif.paramsObj.circuitnameDest,
            username_action
          );
        } else {
          newdescr = i18n.__('CIRCUIT_ADDED_ADMIN', sender, recnotif.paramsObj.circuitnameDest, username_action);
          recnotif.openUrl = '/my/' + sender;
        }
        tag = 'addadmingrp';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_REMOVED_ADMIN) {
        if (sender === recnotif.paramsObj.usernameDest) {
          newdescr = i18n.__(
            'CIRCUIT_REMOVED_ADMIN_YOU',
            recnotif.paramsObj.usernameDest,
            recnotif.paramsObj.circuitnameDest,
            username_action
          );
        } else {
          newdescr = i18n.__('CIRCUIT_REMOVED_ADMIN', sender, recnotif.paramsObj.circuitnameDest, username_action);
          recnotif.openUrl = '/my/' + sender;
        }
        tag = 'removeadmincircuit';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_SENDCOINSREQ) {
        if (groupOComdest) {
          newdescr = i18n.__(
            'CIRCUIT_SENDCOINSREQ_GROUP',
            tools.getAhref(username_action, await tools.getLinkUserTelegram(recnotif.idapp, username_action)),
            qty,
            symbol,
            strtipocontoDest,
            groupOComdest,
            circuitname
          );
        } else if (groupOComorig && sender === recnotif.paramsObj.usernameDest) {
          newdescr = i18n.__(
            'CIRCUIT_SENDCOINSREQ_FROM_GROUP_TO_YOU',
            strtipocontoOrig,
            groupOComorig,
            username_action,
            qty,
            symbol,
            recnotif.paramsObj.extrarec.dest,
            circuitname
          );
        } else if (groupOComorig) {
          newdescr = i18n.__(
            'CIRCUIT_SENDCOINSREQ_FROM_GROUP_TO_USER',
            strtipocontoOrig,
            groupOComorig,
            username_action,
            qty,
            symbol,
            recnotif.paramsObj.extrarec.dest,
            circuitname
          );
        } else {
          newdescr = i18n.__(
            'CIRCUIT_SENDCOINSREQ',
            tools.getAhref(username_action, await tools.getLinkUserTelegram(recnotif.idapp, username_action)),
            qty,
            symbol,
            circuitname
          );
        }

        tag = 'sendcoin';
        recnotif.openUrl =
          shared_consts.getDirectoryByTable(shared_consts.TAB_MYCIRCUITS, true) + recnotif.paramsObj.path; //++Todo: dove lo mando ?
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_SENDCOINSREQ_SENT) {
        if (myorig) {
          if (groupOComdest) {
            newdescr = i18n.__(
              'CIRCUIT_SENDCOINSREQ_FROM_GROUP_TO_GROUP',
              strtipocontoOrig,
              myorig,
              username_action,
              qty,
              symbol,
              strtipocontoDest,
              groupOComdest,
              circuitname
            );
          } else {
            newdescr = i18n.__(
              'CIRCUIT_SENDCOINSREQ_FROM_GROUP_TO_USER',
              strtipocontoOrig,
              myorig,
              username_action,
              qty,
              symbol,
              mydest,
              circuitname
            );
          }
        } else {
          if (groupOComdest) {
            newdescr = i18n.__(
              'CIRCUIT_SENDCOINSREQ_TO_GROUP',
              qty,
              symbol,
              strtipocontoDest,
              groupOComdest,
              circuitname
            );
          } else {
            newdescr = i18n.__('CIRCUIT_SENDCOINSREQ_TO_ME', qty, symbol, mydest, circuitname);
          }
        }

        tag = 'sendcoin';
        recnotif.openUrl =
          shared_consts.getDirectoryByTable(shared_consts.TAB_MYCIRCUITS, true) + recnotif.paramsObj.path; //++Todo: dove lo mando ?
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_COINS_ACCEPTED) {
        newdescr =
          i18n.__('ID_CIRCUIT_COINS_ACCEPTED', qty, symbol, username_action, circuitname) +
          `\n` +
          i18n.__('SALDO_UPDATE', recnotif.paramsObj.extrarec.saldoDest, symbol, circuitname);

        if (myorig) {
          if (groupOComdest) {
            newdescr =
              i18n.__(
                'ID_CIRCUIT_COINS_ACCEPTED_FROM_GROUP_TO_GROUP',
                strtipocontoDest,
                myorig,
                username_action,
                qty,
                symbol,
                strtipocontoDest,
                groupOComdest,
                circuitname,
                username_mittente
              ) +
              `\n` +
              i18n.__('SALDO_UPDATE', recnotif.paramsObj.extrarec.saldoDest, symbol, circuitname);
          } else {
            newdescr =
              i18n.__(
                'ID_CIRCUIT_COINS_ACCEPTED_FROM_GROUP_TO_YOU',
                qty,
                symbol,
                strtipocontoOrig,
                myorig,
                circuitname,
                username_action
              ) +
              `\n` +
              i18n.__('SALDO_UPDATE', recnotif.paramsObj.extrarec.saldoDest, symbol, circuitname);
          }
        } else {
          if (groupOComdest) {
            newdescr =
              i18n.__(
                'ID_CIRCUIT_COINS_ACCEPTED_FROM_ME_TO_GROUP',
                strtipocontoDest,
                groupOComdest,
                username_action,
                qty,
                symbol,
                username_mittente
              ) +
              `\n` +
              i18n.__('SALDO_UPDATE', recnotif.paramsObj.extrarec.saldoDest, symbol, circuitname);
          } else {
            newdescr =
              i18n.__('ID_CIRCUIT_COINS_ACCEPTED_FROM_ME_TO_YOU', qty, symbol, username_action, circuitname) +
              `\n` +
              i18n.__('SALDO_UPDATE', recnotif.paramsObj.extrarec.saldoDest, symbol, circuitname);
          }
        }

        tag = 'sendcoin';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_COINS_ACCEPTED_SENT) {
        if (!destinatario) {
          destinatario = username_action;
        }
        let saldostr = i18n.__('SALDO_UPDATE', recnotif.paramsObj.extrarec.saldoOrig, symbol, circuitname);
        if (groupOComorig) {
          saldostr = i18n.__(
            'SALDO_UPDATE_WHO',
            groupOComorig,
            recnotif.paramsObj.extrarec.saldoOrig,
            symbol,
            circuitname
          );
        }

        newdescr = i18n.__('ID_CIRCUIT_COINS_ACCEPTED_TO_ME', qty, symbol, destinatario, circuitname) + `\n` + saldostr;
        tag = 'sendcoin';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_COINS_REFUSED) {
        newdescr = i18n.__('ID_CIRCUIT_COINS_REFUSED', qty, symbol, username_action, circuitname);
        tag = 'sendcoin';
      } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_COINS_REFUSED_SENT) {
        newdescr = i18n.__('ID_CIRCUIT_COINS_REFUSED_TO_ME', qty, symbol, destinatario, circuitname);
        tag = 'sendcoin';
      }
    } else if (recnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_FAVORITE) {
      // ++ Controlla se esiste già
      let esitegia = recnotif.paramsObj.recObjCreator.exist; // ++

      if (esitegia)
        newdescr = i18n.__(
          'SET_FAVORITE_OTHERS',
          recnotif.paramsObj.username_action,
          recnotif.paramsObj.recObjCreator.numfav - 1,
          recnotif.paramsObj.recObjCreator.descr
        );
      else
        newdescr = i18n.__('SET_FAVORITE', recnotif.paramsObj.username_action, recnotif.paramsObj.recObjCreator.descr);

      tag = 'favorite';

      recnotif.openUrl =
        shared_consts.getDirectoryByTable(recnotif.paramsObj.recObjCreator.table, true) +
        recnotif.paramsObj.recObjCreator.id;
      recnotif.linkaddTelegram = i18n.__('SHOW_POST');
    }

    recnotif.tag = recnotif.tag ? recnotif.tag : tag;

    if (!recnotif.descr) {
      recnotif.descr = newdescr;
    }

    return recnotif;
  } catch (e) {
    console.error(e);
    return null;
  }
};

sendNotifSchema.statics.compileOtherFields = async function (arrnotif) {
  const { User } = require('../models/user');

  try {
    // Fill in the image profile of the semyinders !
    for (const notif of arrnotif) {
      let myimgprofile = await User.findOne(
        { idapp: notif.idapp, username: notif.sender },
        { 'profile.img': 1 }
      ).lean();
      if (myimgprofile && myimgprofile.profile.img)
        notif.myimgsender = 'upload/profile/' + notif.sender + '/' + myimgprofile.profile.img;
      else notif.myimgsender = '/images/noimg-user.svg';
    }

    return arrnotif;
  } catch (e) {
    console.error(e);
    return arrnotif;
  }
};

sendNotifSchema.statics.findLastNotifsByUserIdAndIdApp = function (username, idapp, limit) {
  const SendNotif = this;

  return SendNotif.aggregate([
    {
      $match: {
        idapp,
        dest: username,
        typedir: { $ne: shared_consts.TypeNotifs.TYPEDIR_CIRCUITS },
      },
    },
    { $limit: limit },
    {
      $sort: { datenotif: -1 },
    },
  ])
    .then(async (arrnotif) => {
      return this.compileOtherFields(arrnotif);
    })
    .catch((err) => {
      console.error(err);
    });
};

sendNotifSchema.statics.findLastNotifCoinsByUserIdAndIdApp = function (username, idapp, limit, inattesa) {
  const SendNotif = this;

  let filter = {
    idapp,
    typedir: shared_consts.TypeNotifs.TYPEDIR_CIRCUITS,
    dest: username,
  };

  if (inattesa) {
    filter.status = 0;
  } else {
    filter.status = { $ne: 0 };
  }

  return SendNotif.aggregate([
    {
      $match: filter,
    },
    { $limit: limit },
    {
      $sort: { datenotif: -1 },
    },
  ])
    .then(async (arrnotif) => {
      return this.compileOtherFields(arrnotif);
    })
    .catch((err) => {
      console.error(err);
    });
};

sendNotifSchema.statics.findAllNotifCoinsAllIdAndIdApp = function (idapp) {
  const SendNotif = this;

  let filter = {
    idapp,
    typedir: shared_consts.TypeNotifs.TYPEDIR_CIRCUITS,
    typeid: shared_consts.TypeNotifs.ID_CIRCUIT_SENDCOINSREQ,
    status: 0,
    'extrarec.circuitname': { $ne: 'Circuito di TEST' },
    'extrarec.symbol': { $ne: 'RISTeST' },
  };

  return SendNotif.aggregate([
    {
      $match: filter,
    },
    {
      $sort: { datenotif: -1 },
    },
  ])
    .then(async (arrnotif) => {
      return this.compileOtherFields(arrnotif);
    })
    .catch((err) => {
      console.error(err);
    });
};

sendNotifSchema.statics.saveAndSendNotif = async function (myrecnotif, req, res, user, paramsObj) {
  const SendNotif = this;

  let idapp = req.body.idapp;
  let check = tools.checkUserOk(myrecnotif.sender, user ? myrecnotif.sender : req.user.username, res);
  if (!check) check = tools.checkUserOk(myrecnotif.sendergroup, user ? myrecnotif.sendergroup : req.user.username, res);
  if (check.exit) return check.ret;

  const { myrecout, save } = await SendNotif.updateStatusAndDescr(myrecnotif, false, req.user.username);
  if (!myrecout) return null;

  // console.log('myrecout._id', myrecout._id.toString());

  let risnotif = null;

  if (save) {
    let res = null;
    try {
      res = await myrecout.save();
      if (res) {
        const idobj = res._id;

        const myrecread = await SendNotif.findById(idobj).lean();
        // console.log('myrecread._id', myrecread._id.toString());

        if (myrecread)
          risnotif = await globalTables.sendNotifCmd(
            myrecread.typedir,
            myrecread.typeid,
            res,
            idapp,
            user ? user : req.user,
            myrecread,
            paramsObj
          );
        else return false;
      }
    } catch (e) {
      console.log(e.message);
      return null;
    }
  } else {
    risnotif = await globalTables.sendNotifCmd(
      myrecout.typedir,
      myrecout.typeid,
      res,
      idapp,
      user ? user : req.user,
      myrecout,
      paramsObj
    );
  }

  return risnotif;
};

sendNotifSchema.statics.updateStatusAndDescr = async function (myrecnotif, onlysave, userorig) {
  const SendNotif = this;

  try {
    if (!myrecnotif.openUrl) {
      // If not exist, then I set openUrl and description
      myrecnotif = await this.getDescrAndLinkByRecNotif(myrecnotif, userorig);
    }

    let newstatus = 0;
    let idnotiftosearch = '';
    let typeidsearch = 0;
    let dest = '';

    let sender = myrecnotif.sender ? myrecnotif.sender : '';
    let newdest = myrecnotif.dest ? myrecnotif.dest : '';
    let sendergroup = myrecnotif.sendergroup ? myrecnotif.sendergroup : '';
    let newdestgroup = myrecnotif.destgroup ? myrecnotif.destgroup : '';

    // Controllare se devo modificare un Notif già esistente !
    if (myrecnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_FRIENDS) {
      typeidsearch = shared_consts.TypeNotifs.ID_FRIENDS_NEW_REC;
      if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_FRIENDS_ACCEPTED) {
        newstatus = shared_consts.StatusNotifs.STATUS_FRIENDS_ACCEPTED;
        dest = myrecnotif.sender;
      } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_FRIENDS_ACCEPTED_MY_REQUEST) {
        newstatus = shared_consts.StatusNotifs.STATUS_FRIENDS_ACCEPTED;
        newdest = myrecnotif.sender;
        sender = myrecnotif.dest;
      } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_FRIENDS_REFUSED) {
        newstatus = shared_consts.StatusNotifs.STATUS_FRIENDS_REFUSED;
        dest = myrecnotif.sender;
      }
    } else if (myrecnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_GROUPS) {
      typeidsearch = shared_consts.TypeNotifs.ID_GROUP_NEW_REC;
      dest = myrecnotif.dest;
      if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_ACCEPTED) {
        typeidsearch = shared_consts.TypeNotifs.ID_GROUP_REQUEST_TO_ENTER;
        newstatus = shared_consts.GroupsNotifs.STATUS_GROUPS_ACCEPTED;
      } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_REFUSED) {
        typeidsearch = shared_consts.TypeNotifs.ID_GROUP_REQUEST_TO_ENTER;
        newstatus = shared_consts.GroupsNotifs.STATUS_GROUPS_REFUSED;
      } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_REMOVED) {
        newstatus = shared_consts.GroupsNotifs.STATUS_GROUPS_REMOVED;
      } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_BLOCK_USER) {
        newstatus = shared_consts.GroupsNotifs.STATUS_GROUPS_BLOCKED;
      } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_DELETE_USER) {
        newstatus = shared_consts.GroupsNotifs.STATUS_GROUPS_DELETED;
      }
    } else if (myrecnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_CIRCUITS) {
      if (myrecnotif.paramsObj.extrarec) idnotiftosearch = myrecnotif.paramsObj.extrarec.notifId;

      typeidsearch = shared_consts.TypeNotifs.ID_CIRCUIT_NEW_REC;
      dest = myrecnotif.dest;
      if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_ACCEPTED) {
        typeidsearch = shared_consts.TypeNotifs.ID_CIRCUIT_REQUEST_TO_ENTER;
        newstatus = shared_consts.CircuitsNotif.STATUS_ACCEPTED;
      } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_REFUSED) {
        typeidsearch = shared_consts.TypeNotifs.ID_CIRCUIT_REQUEST_TO_ENTER;
        newstatus = shared_consts.CircuitsNotif.STATUS_REFUSED;
      } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_REMOVED) {
        newstatus = shared_consts.CircuitsNotif.STATUS_REMOVED;
      } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_BLOCK_USER) {
        newstatus = shared_consts.CircuitsNotif.STATUS_BLOCKED;
      } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_DELETE_USER) {
        newstatus = shared_consts.CircuitsNotif.STATUS_DELETED;
      } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_COINS_ACCEPTED) {
        typeidsearch = shared_consts.TypeNotifs.ID_CIRCUIT_SENDCOINSREQ;
        newstatus = shared_consts.CircuitsNotif.STATUS_COINS_ACCEPTED;
      } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_COINS_REFUSED) {
        typeidsearch = shared_consts.TypeNotifs.ID_CIRCUIT_SENDCOINSREQ;
        newstatus = shared_consts.CircuitsNotif.STATUS_COINS_REFUSED;
      } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_COINS_ACCEPTED_SENT) {
        typeidsearch = shared_consts.TypeNotifs.ID_CIRCUIT_SENDCOINSREQ_SENT;
        if (myrecnotif.paramsObj.extrarec.hasOwnProperty('notifIdToUpdate'))
          idnotiftosearch = myrecnotif.paramsObj.extrarec.notifIdToUpdate;
        if (myrecnotif.paramsObj.extrarec.hasOwnProperty('idStatusToSent'))
          idnotiftosearch = myrecnotif.paramsObj.extrarec.idStatusToSent;

        newstatus = shared_consts.CircuitsNotif.STATUS_COINS_ACCEPTED_SENT;
      } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_COINS_REFUSED_SENT) {
        typeidsearch = shared_consts.TypeNotifs.ID_CIRCUIT_SENDCOINSREQ_SENT;
        if (myrecnotif.paramsObj.extrarec.hasOwnProperty('notifIdToUpdate'))
          idnotiftosearch = myrecnotif.paramsObj.extrarec.notifIdToUpdate;
        if (myrecnotif.paramsObj.extrarec.hasOwnProperty('idStatusToSent'))
          idnotiftosearch = myrecnotif.paramsObj.extrarec.idStatusToSent;

        newstatus = shared_consts.CircuitsNotif.STATUS_COINS_REFUSED_SENT;
      }
    }

    if (newstatus) {
      let fields_to_update = {
        status: newstatus,
        read: false,
        descr: myrecnotif.descr,
        datenotif: new Date(),
        sender,
        dest: newdest,
        sendergroup,
        destgroup: newdestgroup,
      };

      let query = {
        idapp: myrecnotif.idapp,
        typedir: myrecnotif.typedir,
        typeid: typeidsearch,
        dest,
        deleted: false,
        status: 0,
      };

      if (idnotiftosearch) {
        query = {
          _id: idnotiftosearch,
          status: 0,
        };

        fields_to_update = {
          status: newstatus,
          read: false,
          descr: myrecnotif.descr,
          datenotif: new Date(),
        };

        // Cerca il record e se lo trova lo aggiorna
        const myrec = await SendNotif.findOneAndUpdate(
          query,
          { $set: fields_to_update },
          { returnDocument: 'after' }
        ).lean();

        if (myrec) {
          return { myrecout: myrec, save: true };
        }
      }
    }

    // myrecnotif._id = new ObjectId();
    if (newstatus > 0) {
      myrecnotif.status = newstatus;
    }

    return { myrecout: myrecnotif, save: true };
  } catch (e) {
    console.error(e);
    return { myrecout: null, save: false };
  }
};

sendNotifSchema.statics.getStatus = async function (notifId) {
  const SendNotif = this;

  try {
    return await SendNotif.findOne({ _id: notifId }, { status: 1 })
      .lean()
      .then((rec) => rec.status);
  } catch (e) {
    return 0;
  }
};

sendNotifSchema.statics.checkIfCoinsAlreadySent = async function (notifId) {
  const SendNotif = this;

  try {
    const status = await SendNotif.getStatus(notifId);

    if (status !== null) {
      return (
        status === shared_consts.CircuitsNotif.STATUS_COINS_ACCEPTED ||
        status === shared_consts.CircuitsNotif.STATUS_COINS_REFUSED
      );
    }

    return true;
  } catch (e) {
    // If Error, don't send the coins
    return true;
  }
};

sendNotifSchema.statics.saveNotif = async function (myrecnotif, req) {
  const SendNotif = this;

  const { myrecout, save } = await SendNotif.updateStatusAndDescr(myrecnotif, true, req.user.username);
  if (!myrecout) return null;

  return await myrecout
    .save()
    .then((writeresult) => {
      let idobj = writeresult._id;
      return SendNotif.findById(idobj)
        .lean()
        .then(async (recnotif) => {
          return recnotif;
        });
    })
    .catch((e) => {
      console.log(e.message);
      return null;
    });
};

sendNotifSchema.statics.getDefaultRec = function (req) {
  return {
    idapp: req.body.idapp,
    typedir: '',
    typeid: '',
    sender: req.user ? req.user.username : '',
    sendergroup: '',
    dest: '',
    destgroup: '',
    descr: '',
    openUrl: '',
    datenotif: new Date(),
    status: 0,
    read: false,
    tablerec: '',
    idrec: 0,
  };
};

sendNotifSchema.statics.getExtraParam = function (myrecnotif, paramsObj) {
  let out = myrecnotif;
  //if (myrecnotif._doc) {
  //out = myrecnotif._doc
  //}
  out.paramsObj = paramsObj;
  out.options = paramsObj.options ? paramsObj.options : [];
  out.typesend = paramsObj.typesend ? paramsObj.typesend : 0;
  out.extrarec = paramsObj.extrarec ? paramsObj.extrarec : {};
  if (myrecnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_CIRCUITS) {
    out.extrafield = paramsObj.circuitnameDest ? paramsObj.circuitnameDest : '';
  } else if (myrecnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_GROUPS) {
    out.extrafield = paramsObj.groupnameDest ? paramsObj.groupnameDest : '';
  }

  return myrecnotif;
};

sendNotifSchema.statics.createNewNotification = async function (req, res, paramsObj, table, rec, typedir, typeid) {
  const SendNotif = this;

  try {
    let myrecnotif = new SendNotif(this.getDefaultRec(req));
    myrecnotif = this.getExtraParam(myrecnotif, paramsObj);

    myrecnotif.tablerec = table;
    if (rec && table) {
      myrecnotif.idrec = rec._id;
      try {
        if (rec.photos && rec.photos[0]) {
          const mydir =
            tools.getHostByIdApp(myrecnotif.idapp) +
            server_constants.DIR_UPLOAD +
            '/' +
            shared_consts.getDirectoryImgByTable(table, rec.username);
          myrecnotif.img = mydir + rec.photos[0].imagefile;
        }
      } catch (e) {
        console.error('createNewNotification', e);
      }
    }

    myrecnotif.typedir = typedir;
    myrecnotif.typeid = typeid;

    await SendNotif.sendToTheDestinations(myrecnotif, req, res);

    return true;
  } catch (e) {
    console.error('createNewNotification', e);
    return false;
  }
};

sendNotifSchema.statics.createNewNotifToSingleUser = async function (req, res, paramsObj, onlysave, typedir, typeid) {
  const SendNotif = this;

  try {
    let myrecnotif = new SendNotif(this.getDefaultRec(req));
    myrecnotif.typedir = typedir;
    myrecnotif.typeid = typeid;

    myrecnotif = this.getExtraParam(myrecnotif, paramsObj);

    return await SendNotif.sendToSingleUserDest(myrecnotif, req, res, onlysave, paramsObj);
  } catch (e) {
    console.error('createNewNotification', e);
    return null;
  }
};

// Funzione 1: Raccoglie gli username dei destinatari
sendNotifSchema.statics.getNotificationRecipients = async function (myrecnotifpass, req) {
  const { User } = require('../models/user');
  const { City } = require('../models/city');

  try {
    // Recupera la lista utenti
    const userlist = await User.find(
      {
        idapp: myrecnotifpass.idapp,
        $or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
      },
      {
        name: 1,
        surname: 1,
        lasttimeonline: 1,
        lang: 1,
        username: 1,
        'profile.notifs': 1,
        'profile.mycircuits': 1,
        'profile.resid_str_comune': 1,
        'profile.resid_province': 1,
        'profile.resid_card': 1,
        'profile.notif_idCities': 1,
        'profile.notif_provinces': 1,
        'profile.notif_regions': 1,
        'profile.notif_sectors': 1,
        'profile.notif_sector_goods': 1,
      }
    ).lean();

    let arrcircuits = [];
    let arrprovinces = [];
    let arrregions = [];
    let idSector = 0;

    const mytable = globalTables.getTableByTableName(myrecnotifpass.tablerec);

    // Prepara i dati geografici e di settore
    if (
      myrecnotifpass.typedir === shared_consts.TypeNotifs.TYPEDIR_BACHECA ||
      myrecnotifpass.typedir === shared_consts.TypeNotifs.TYPEDIR_EVENTS
    ) {
      if (
        shared_consts.TABLES_ADV_NOTIFICATION.includes(myrecnotifpass.tablerec) ||
        shared_consts.TABLES_EVENTS_NOTIFICATION.includes(myrecnotifpass.tablerec)
      ) {
        if (myrecnotifpass.idrec && myrecnotifpass.idrec !== '0') {
          const myrectableorig = await mytable.getCompleteRecord(myrecnotifpass.idapp, myrecnotifpass.idrec);
          if (myrectableorig) {
            for (const city of myrectableorig.idCity) {
              const prov = await City.getProvinceByIdCity(city);
              arrprovinces.push(prov);
              arrregions.push(await City.getRegionByIdCity(city));
              arrcircuits.push(await City.getCircuitNameBystrProv(prov));
            }

            if (myrecnotifpass.tablerec === shared_consts.TABLES_MYGOODS) {
              idSector = myrectableorig.idSectorGood;
            } else if (myrecnotifpass.tablerec === shared_consts.TABLES_MYBACHECAS) {
              idSector = myrectableorig.idSectorBacheca;
            } else {
              idSector = myrectableorig.idSector;
            }
          }
          myrecnotifpass.myrectableorig = myrectableorig;
        }
      }
    }

    // Array per raccogliere i destinatari
    const recipients = [];

    // Filtra gli utenti che devono ricevere la notifica
    for (const user of userlist) {
      try {
        if (!user.profile || !user.profile.notifs) {
          continue;
        }

        const usernotifprofile = user.profile.notifs.find((notif) => notif.dir === myrecnotifpass.typedir);
        let send = false;

        // Logica per TYPEDIR_EVENTS
        if (myrecnotifpass.typedir === shared_consts.TypeNotifs.TYPEDIR_EVENTS) {
          if (myrecnotifpass.tablerec === shared_consts.TABLES_MYBACHECAS) {
            if (
              usernotifprofile &&
              tools.isBitActive(usernotifprofile.value, shared_consts.TypeNotifs.ID_EVENTS_ATTEND)
            ) {
              send = true;
            }
          }
        }

        // Logica per TYPEDIR_FAVORITE
        if (myrecnotifpass.typedir === shared_consts.TypeNotifs.TYPEDIR_FAVORITE) {
          if (shared_consts.TABLES_FAVORITE_BOOKMARK.includes(myrecnotifpass.tablerec)) {
            if (
              usernotifprofile &&
              tools.isBitActive(usernotifprofile.value, shared_consts.TypeNotifs.ID_FAVORITE_ADDED)
            ) {
              send = true;
            }
          }
        }
        // Logica per TYPEDIR_BACHECA, TYPEDIR_EVENTS, TYPEDIR_GROUPS
        else if (
          myrecnotifpass.typedir === shared_consts.TypeNotifs.TYPEDIR_BACHECA ||
          myrecnotifpass.typedir === shared_consts.TypeNotifs.TYPEDIR_EVENTS ||
          myrecnotifpass.typedir === shared_consts.TypeNotifs.TYPEDIR_GROUPS
        ) {
          if (
            shared_consts.TABLES_ADV_NOTIFICATION.includes(myrecnotifpass.tablerec) ||
            shared_consts.TABLES_EVENTS_NOTIFICATION.includes(myrecnotifpass.tablerec) ||
            shared_consts.TABLES_GROUPS_NOTIFICATION.includes(myrecnotifpass.tablerec)
          ) {
            // Controllo provincia di residenza
            if (
              usernotifprofile &&
              tools.isBitActive(usernotifprofile.value, shared_consts.UsersNotif.NEW_ADV_YOUR_PROVINCE) &&
              user.profile.resid_province &&
              arrprovinces.indexOf(user.profile.resid_province) >= 0
            ) {
              send = true;
            }

            // Controllo province selezionate
            if (
              usernotifprofile &&
              tools.isBitActive(usernotifprofile.value, shared_consts.UsersNotif.NEW_ADV_PROVINCE) &&
              user.profile.notif_provinces &&
              user.profile.notif_provinces.some((r) => arrprovinces.indexOf(r) >= 0)
            ) {
              send = true;
            }

            // Controllo regioni
            if (
              usernotifprofile &&
              tools.isBitActive(usernotifprofile.value, shared_consts.UsersNotif.NEW_ADV_REGION) &&
              user.profile.notif_regions &&
              user.profile.notif_regions.some((r) => arrregions.indexOf(r) >= 0)
            ) {
              send = true;
            }

            // Controllo circuiti
            if (
              usernotifprofile &&
              tools.isBitActive(usernotifprofile.value, shared_consts.UsersNotif.NEW_ADV_MY_RIS_CIRCUIT) &&
              user.profile.mycircuits &&
              user.profile.mycircuits.some((r) => arrcircuits.indexOf(r.circuitname) >= 0)
            ) {
              send = true;
            }

            // Controllo settore
            if (
              idSector &&
              usernotifprofile &&
              tools.isBitActive(usernotifprofile.value, shared_consts.UsersNotif.NEW_ADV_SECTOR)
            ) {
              if (myrecnotifpass.tablerec === shared_consts.TABLES_MYGOODS) {
                if (user.profile.notif_sector_goods) {
                  send = send && user.profile.notif_sector_goods.includes(idSector);
                }
              } else if (user.profile.notif_sectors) {
                send = send && user.profile.notif_sectors.includes(idSector);
              }
            }
          }
        }

        if (send) {
          recipients.push({
            username: user.username,
            user: user,
          });
        }
      } catch (e) {
        console.error('❌ Error: getNotificationRecipients - user', user.username, 'Err:', e);
      }
    }

    return recipients;
  } catch (e) {
    console.error('getNotificationRecipients', e);
    return [];
  }
};

// Funzione 2: Invia le notifiche ai destinatari
sendNotifSchema.statics.sendToTheDestinations = async function (myrecnotifpass, req, res) {
  const SendNotif = this;

  try {
    // Ottieni l'array dei destinatari
    const recipients = await this.getNotificationRecipients(myrecnotifpass, req);

    // Prepara i dati della notifica
    myrecnotifpass = await this.getDescrAndLinkByRecNotif(myrecnotifpass, req.user.username);
    delete myrecnotifpass._doc['_id'];

    myrecnotifpass.inviaaListaUtenti = true;
    
    if (recipients) {
      console.log(
        `*** INVIO DI ${recipients.length} MESSAGGI / NOTIFICHE : \n"${myrecnotifpass.textcontent_Telegram || myrecnotifpass.descr}"...`
      );
    }

    let myrecnotif = new SendNotif(myrecnotifpass);
    // Cicla sui destinatari e invia le notifiche
    for (const recipient of recipients) {
      try {
        myrecnotif.dest = recipient.username;
        await SendNotif.saveAndSendNotif(myrecnotif, req, res, recipient.user);
      } catch (e) {
        console.error('❌ Error: sendToTheDestinations - sending to', recipient.username, 'Err:', e);
      }
    }

    return true;
  } catch (e) {
    console.error('sendToTheDestinations', e);
    return false;
  }
};

sendNotifSchema.statics.sendToSingleUserDest = async function (myrecnotif, req, res, onlysave, paramsObj) {
  const SendNotif = this;

  try {
    myrecnotif.dest =
      myrecnotif.paramsObj && myrecnotif.paramsObj.usernameDest ? myrecnotif.paramsObj.usernameDest : '';
    myrecnotif.username_worked =
      myrecnotif.paramsObj && myrecnotif.paramsObj.username_worked
        ? myrecnotif.paramsObj.username_worked
        : myrecnotif.dest;

    if (onlysave) {
      return await SendNotif.saveNotif(myrecnotif, req, paramsObj);
    } else {
      return await SendNotif.saveAndSendNotif(myrecnotif, req, res, null, paramsObj);
    }
  } catch (e) {
    console.error('sendToSingleUserDest', e);
    return false;
  }
};

sendNotifSchema.statics.getSumPendingTransactionsMittente = async function (idapp, username, circuitname, groupname) {
  const SendNotif = this;

  try {
    let query = {
      idapp,
      sender: username,
      typedir: shared_consts.TypeNotifs.TYPEDIR_CIRCUITS,
      typeid: shared_consts.TypeNotifs.ID_CIRCUIT_SENDCOINSREQ,
      status: 0,
      'extrarec.circuitname': circuitname,
    };

    if (groupname) {
      query.sendergroup = groupname;
    }

    return await SendNotif.find(query).lean();
  } catch (e) {
    console.error('e', e);
  }
};

sendNotifSchema.statics.getSumPendingTransactionsDest = async function (idapp, username, circuitname, groupname) {
  const SendNotif = this;

  try {
    let query = {
      idapp,
      sender: username,
      typedir: shared_consts.TypeNotifs.TYPEDIR_CIRCUITS,
      typeid: shared_consts.TypeNotifs.ID_CIRCUIT_SENDCOINSREQ,
      status: 0,
      'extrarec.circuitname': circuitname,
      'extrarec.dest': username,
    };

    if (groupname) {
      query.sendergroup = groupname;
      query.extrarec.groupdest = groupname;
    }

    return await SendNotif.find(query).lean();
  } catch (e) {
    console.error('e', e);
  }
};

sendNotifSchema.statics.RemovePendentTransactions = async function (idapp) {
  const SendNodif = this;

  try {
    const result = await SendNodif.deleteMany({
      idapp,
      typedir: shared_consts.TypeNotifs.TYPEDIR_CIRCUITS,
      typeid: shared_consts.TypeNotifs.ID_CIRCUIT_SENDCOINSREQ,
      status: 0,
    });
    return result;
  } catch (error) {
    console.error('Error deleting documents:', error);
    throw error;
  }
};

sendNotifSchema.statics.RemoveOldNotif = async function (idapp, numgg) {
  const SendNodif = this;

  const currentDate = new Date();
  const limitDate = new Date(currentDate.setDate(currentDate.getDate() - numgg));

  return await SendNodif.deleteMany({
    idapp,
    date_created: { $lt: limitDate },
    // typedir: { $ne: shared_consts.TypeNotifs.TYPEDIR_CIRCUITS },
    $or: [{ typeid: { $ne: shared_consts.TypeNotifs.ID_CIRCUIT_SENDCOINSREQ } }, { status: { $ne: 0 } }],
  });
};

sendNotifSchema.statics.RemoveOldNotif90 = async function (idapp) {
  return this.RemoveOldNotif(idapp, 90);
};

sendNotifSchema.statics.RemoveOldNotif30 = async function (idapp) {
  return this.RemoveOldNotif(idapp, 30);
};

sendNotifSchema.statics.updatePendingTransactions = async function (recnotif) {
  const { Circuit } = require('../models/circuit');
  const { Account } = require('../models/account');

  try {
    if (recnotif && recnotif.extrarec && recnotif.extrarec.circuitname) {
      const circuit = await Circuit.getCircuitByName(recnotif.idapp, recnotif.extrarec.circuitname);

      const accountdestTable = await Account.getAccountByUsernameAndCircuitId(
        recnotif.idapp,
        recnotif.extrarec.dest,
        circuit._id,
        true,
        false,
        recnotif.extrarec.groupdest,
        recnotif.extrarec.contoComDest
      );
      const accountorigTable = await Account.getAccountByUsernameAndCircuitId(
        recnotif.idapp,
        recnotif.sender,
        circuit._id,
        true,
        true,
        recnotif.extrarec.grouporig,
        recnotif.extrarec.contoComOrig
      );

      if (accountdestTable) await accountdestTable.calcPending(false);
      if (accountorigTable) await accountorigTable.calcPending(true);
    }
  } catch (e) {
    console.error(e);
  }
};

sendNotifSchema.statics.checkIfAlreadyExist = async function (idapp, tag, idpost, numtab) {};

const SendNotif = mongoose.model('SendNotif', sendNotifSchema);

module.exports = { SendNotif: SendNotif };
