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

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

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


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

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

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

const reactionSchema = new Schema({
  idapp: {
    type: String,
  },
  userId: {
    type: String,
  },
  username: {
    type: String,
  },
  idrec: {
    type: String,
  },
  tab: {
    type: Number,
  },
  fav: {
    type: Boolean,
  },
  book: {
    type: Boolean,
  },
  seen: {
    type: Boolean,
  },
  attend: {
    type: Boolean,
  },
});

reactionSchema.statics.getFieldsForReactions = function () {
  let reactionsField = {
    numseen: {
      type: Number,
    },
    numbook: {
      type: Number,
    },
    numfav: {
      type: Number,
    },
    numattend: {
      type: Number,
    },
  };

  return reactionsField;
};

reactionSchema.statics.getReactionsCounts = async function (mytable, idapp, idrec, numtab) {

  let query = [];

  try {

    query =
      [
        {
          $match: {
            _id: idrec,
          },

        },
        {
          $lookup: {
            from: "reactions",
            let: {
              tab: numtab,
              id: '$_id',
            },
            pipeline: [
              {
                $match: {
                  $expr: {
                    $and: [
                      { $eq: ['$idrec', idrec] },
                      { $eq: ['$tab', numtab] },
                      { $eq: ['$idapp', idapp] },
                    ],
                  },
                },
              },
              {
                $group: {
                  _id: "$idrec",
                  numseen: {
                    $sum: {
                      $cond: {
                        if: { $ifNull: ["$seen", false] }, // Check if the field exists and is not null
                        then: 1, // Increment count by 1 if the field exists
                        else: 0, // Otherwise, keep the count unchanged
                      }
                    }
                  },
                  numfav: {
                    $sum: {
                      $cond: {
                        if: { $ifNull: ["$fav", false] }, // Check if the field exists and is not null
                        then: 1, // Increment count by 1 if the field exists
                        else: 0, // Otherwise, keep the count unchanged
                      }
                    }
                  },
                  numbook: {
                    $sum: {
                      $cond: {
                        if: { $ifNull: ["$book", false] }, // Check if the field exists and is not null
                        then: 1, // Increment count by 1 if the field exists
                        else: 0, // Otherwise, keep the count unchanged
                      }
                    }
                  },
                  numattend: {
                    $sum: {
                      $cond: {
                        if: { $ifNull: ["$attend", false] }, // Check if the field exists and is not null
                        then: 1, // Increment count by 1 if the field exists
                        else: 0, // Otherwise, keep the count unchanged
                      }
                    }
                  }
                },
              },
            ],
            as: 'myreact',
          },
        },

        {
          $unwind: {
            path: "$myreact",
            preserveNullAndEmptyArrays: true,
          },
        },

      ];

    const ris = await mytable.aggregate(query);

    return ris ? ris[0]: null;

  } catch (e) {

  }


};

reactionSchema.statics.updateReactionsCounts = async function () {

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

  console.log('INIZIO - updateReactionsCounts');

  try {

    for (const tablestr of shared_consts.TABLES_REACTIONS) {
      const numtab = tools.getNumTabByTable(tablestr);
      const mytable = globalTables.getTableByTableName(tablestr);

      const arrrec = await mytable.find({});

      console.log('   updateReactionsCounts tabella', tablestr);

      for (const rec of arrrec) {
        // Calcola 
        const ris = await Reaction.getReactionsCounts(mytable, idapp, rec._id, numtab);

        if (ris && ris.myreact) {

          risupdate = await mytable.updateOne({ _id: rec._id }, {
            $set: {
              numseen: ris.myreact.numseen | 0,
              numfav: ris.myreact.numfav | 0,
              numbook: ris.myreact.numbook | 0,
              numattend: ris.myreact.numattend | 0,
            }
          })    
        }
      }

    }

    console.log('FINE - updateReactionsCounts');

  } catch (err) {
    console.error(err);
  }

};

;

reactionSchema.statics.getFieldsForSearch = function () {
  return [
    { field: 'username', type: tools.FieldType.string }];
};

reactionSchema.statics.executeQueryTable = function (idapp, params) {
  params.fieldsearch = this.getFieldsForSearch();
  return tools.executeQueryTable(this, 0, params);
};

reactionSchema.statics.calcReactions = async function (idapp, id, tab) {

  try {
    let myquerycountreaction = [
      {
        $match: {
          idapp,
          idrec: id,
          tab,
        },
      },
      {
        $group: {
          _id: null,
          numseen: {
            $sum: {
              $cond: {
                if: { $ifNull: ["$seen", false] }, // Check if the field exists and is not null
                then: 1, // Increment count by 1 if the field exists
                else: 0, // Otherwise, keep the count unchanged
              }
            }
          },
          numfav: {
            $sum: {
              $cond: {
                if: { $ifNull: ["$fav", false] }, // Check if the field exists and is not null
                then: 1, // Increment count by 1 if the field exists
                else: 0, // Otherwise, keep the count unchanged
              }
            }
          },
          numbook: {
            $sum: {
              $cond: {
                if: { $ifNull: ["$book", false] }, // Check if the field exists and is not null
                then: 1, // Increment count by 1 if the field exists
                else: 0, // Otherwise, keep the count unchanged
              }
            }
          },
          numattend: {
            $sum: {
              $cond: {
                if: { $ifNull: ["$attend", false] }, // Check if the field exists and is not null
                then: 1, // Increment count by 1 if the field exists
                else: 0, // Otherwise, keep the count unchanged
              }
            }
          }
        },
      },
    ];

    return await Reaction.aggregate(myquerycountreaction)
      .then((ris) => {
        return ris ? ris[0] : null;
      });

  } catch (err) {
    console.error(err);
  }

};

// Aggiungo il Favorite
reactionSchema.statics.addFavorite = async function (req, idapp, username, id, tab) {

  let ris = null;

  try {
    let ok = false;

    const myrec = await Reaction.findOne({ idrec: id, idapp, username });
    if (!myrec) {
      const myrec = new Reaction({ idrec: id, idapp, userId: req.user.id, username, tab, fav: true });
      ris = await myrec.save();
      ok = ris ? 1 : 0;
    } else {
      ris = await Reaction.updateOne({ idrec: id, idapp, username }, {
        $set: {
          fav: true,
        }
      })
      ok = ris.ok;
    }

    const { SendNotif } = require('../models/sendnotif');

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

    // Invia una Notifica al Destinatario
    const recObjCreator = await globalTables.getUserCreatorByNumTabAndId(idapp, id, tab);

    if (recObjCreator) {
      await SendNotif.createNewNotifToSingleUser(req, null, { usernameDest: recObjCreator.username, recObjCreator, username_action: req.user.username }, false, shared_consts.TypeNotifs.TYPEDIR_FAVORITE,
        shared_consts.TypeNotifs.ID_FAVORITE_ADDED);

    }

    return { ris, ok };

  } catch (e) {
    console.error('Err addFavorite', e);
    return { ris: null, ok: 0 };
  }
};

// Aggiungo il Seen
reactionSchema.statics.addSeen = async function (req, idapp, username, id, tab) {

  const myrec = await Reaction.findOne({ idrec: id, idapp, username });
  if (!myrec) {
    const myrec = new Reaction({ idrec: id, idapp, userId: req.user.id, username, tab, seen: true });
    return await myrec.save()
      .then((ris) => {
        // console.log('salvato proj!');
        return { ris, ok: ris ? 1 : 0 };
      })
      .catch(err => {
        console.log("Error addSeen", err.message);
      });
  } else {
    return Reaction.updateOne({ _id: myrec._id }, {
      $set: {
        seen: true,
      }
    })
  }
};

// Aggiungo il Bookmark
reactionSchema.statics.addBookmark = async function (req, idapp, username, id, tab) {

  const myrec = await Reaction.findOne({ idrec: id, idapp, username });
  if (!myrec) {
    const myrec = new Reaction({ idrec: id, idapp, userId: req.user.id, username, tab, book: true });
    return await myrec.save()
      .then((ris) => {
        return { ris, ok: ris ? 1 : 0 };
      })
      .catch(err => {
        console.log("Error addBookmark", err.message);
      });
  } else {
    return Reaction.updateOne({ _id: myrec._id }, {
      $set: {
        book: true,
      }
    })
  }
};

// Aggiungo il Attend
reactionSchema.statics.addAttend = async function (req, idapp, username, id, tab) {

  const myrec = await Reaction.findOne({ idrec: id, idapp, username });
  if (!myrec) {
    const myrec = new Reaction({ idrec: id, idapp, userId: req.user.id, username, tab, attend: true });
    return await myrec.save()
      .then((ris) => {
        return { ris, ok: ris ? 1 : 0 };
      })
      .catch(err => {
        console.log("Error addAttend", err.message);
      });
  } else {
    return Reaction.updateOne({ _id: myrec._id }, {
      $set: {
        attend: true,
      }
    })
  }
};

// Rimuovo il Favorite
reactionSchema.statics.removeFavorite = async function (
  idapp, username, id, tab) {

  const myrec = await Reaction.findOne({ idrec: id, idapp, username });
  if (myrec) {
    return Reaction.updateOne({ _id: myrec._id }, {
      $set: {
        fav: false,
      }
    })
  }

  return false;


};

// Rimuovo il Bookmark
reactionSchema.statics.removeBookmark = async function (
  idapp, username, id, tab) {

  const myrec = await Reaction.findOne({ idrec: id, idapp, username });
  if (myrec) {
    return Reaction.updateOne({ _id: myrec._id }, {
      $set: {
        book: false,
      }
    })
  }

  return false;


};

const Reaction = mongoose.model('Reaction', reactionSchema);

module.exports = { Reaction };
