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

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

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

const { ObjectID } = require('mongodb');
const { Account } = require('../models/account');

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

const MovementSchema = new Schema({
  _id: {
    type: String,
    default: function () {
      return new ObjectID().toString();
    },
  },
  idapp: {
    type: String,
  },
  notifId: {
    type: String,
  },
  transactionDate: {
    type: Date,
  },
  accountFromId: {
    type: String,
  },
  accountToId: {
    type: String,
  },
  causal_table: {
    type: String,
  },
  causal_IdRec: {
    type: String,
  },
  amount: {
    type: Number,
  },
  causal: {
    type: String,
    default: '',
  },
  residual: {
    type: Number,
    default: 0,
  },
  expiringDate: {
    type: Date,
  },
});

MovementSchema.statics.findAllIdApp = async function (idapp) {
  const MyMovement = this;

  const myfind = { idapp };

  return await MyMovement.find(myfind, (err, arrrec) => {
    return arrrec;
  });
};

MovementSchema.pre('save', async function (next) {
  if (this.isNew) {

    this.transactionDate = new Date();
  }

  next();
});

MovementSchema.statics.getFieldsForSearch = function () {
  return [
    { field: 'causal', type: tools.FieldType.string },
    { field: 'amount', type: tools.FieldType.number },
  ];

};

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

MovementSchema.statics.addMov = async function (idapp, accountFromIdTable, accountToIdTable, amount, causal, notifId) {

  try {
    // Only positive values
    amount = Math.abs(amount);

    let mymov = await Movement.create(
      {
        _id: new ObjectID().toString(),
        idapp,
        transactionDate: new Date(),
        accountFromId: accountFromIdTable._id,
        accountToId: accountToIdTable._id,
        amount,
        causal,
        residual: 0,
        notifId,
        // expiringDate:
      },
    );

    if (mymov) {
      // Update saldo dell'Account
      await Account.addtoSaldo(accountToIdTable, amount, true);

      await Account.addtoSaldo(accountFromIdTable, -amount, false);

      return mymov;
    }
  } catch (e) {
    console.error('Error in addMov', e.message);
  }
};

MovementSchema.statics.getQueryMovsByCircuitId = async function (idapp, username, groupname, contocom, circuitId) {

  try {
    if (!circuitId) {
      return [];
    }
    const myaccount = await Account.getAccountByUsernameAndCircuitId(idapp, username, circuitId, false, true, groupname, contocom);

    if (myaccount) {

      let aggr1 = [
        {
          $match: {
            idapp,
            $or: [
              { accountFromId: myaccount._id },
              { accountToId: myaccount._id }],
          },
        },
        {
          $lookup: {
            from: 'accounts',
            localField: 'accountFromId',
            foreignField: '_id',
            as: 'accfrom',
          },
        },
        { $unwind: '$accfrom' },
        {
          $lookup: {
            from: 'users',
            let: { username: '$accfrom.username', idapp: '$accfrom.idapp' },
            pipeline: [
              {
                $match:
                {
                  $expr:
                  {
                    $and:
                      [
                        { $eq: ['$$username', '$username'] },
                        { $eq: ['$$idapp', '$idapp'] },
                      ],
                  },
                },
              },
            ],
            as: 'userfrom',
          },
        },
        {
          $unwind: {
            path: '$userfrom',
            preserveNullAndEmptyArrays: true,
          },
        },
        {
          $lookup: {
            from: 'mygroups',
            let: { groupname: '$accfrom.groupname', idapp: '$accfrom.idapp' },
            pipeline: [
              {
                $match:
                {
                  $expr:
                  {
                    $and:
                      [
                        { $eq: ['$$groupname', '$groupname'] },
                        { $eq: ['$$idapp', '$idapp'] },
                      ],
                  },
                },
              },
            ],
            as: 'groupfrom',
          },
        },
        {
          $unwind: {
            path: '$groupfrom',
            preserveNullAndEmptyArrays: true,
          },
        },
        
        {
          $lookup: {
            from: 'circuits',
            let: { contocom: '$accfrom.contocom', idapp: '$accfrom.idapp' },
            pipeline: [
              {
                $match:
                {
                  $expr:
                  {
                    $and:
                      [
                        { $eq: ['$$contocom', '$path'] },
                        { $eq: ['$$idapp', '$idapp'] },
                      ],
                  },
                },
              },
            ],
            as: 'contocomfrom',
          },
        },
        {
          $unwind: {
            path: '$contocomfrom',
            preserveNullAndEmptyArrays: true,
          },
        },
        {
          $lookup: {
            from: 'accounts',
            localField: 'accountToId',
            foreignField: '_id',
            as: 'accto',
          },
        },
        { $unwind: '$accto' },
        {
          $lookup: {
            from: 'circuits',
            localField: 'accfrom.circuitId',
            foreignField: '_id',
            as: 'circuitfrom',
          },
        },
        {
          $unwind: '$circuitfrom',
        },
        {
          $lookup: {
            from: 'circuits',
            localField: 'accto.circuitId',
            foreignField: '_id',
            as: 'circuitto',
          },
        },
        {
          $unwind: '$circuitto',
        },
        {
          $lookup: {
            from: 'users',
            let: { username: '$accto.username', idapp: '$accto.idapp' },
            pipeline: [
              {
                $match:
                {
                  $expr:
                  {
                    $and:
                      [
                        { $eq: ['$$username', '$username'] },
                        { $eq: ['$$idapp', '$idapp'] },
                      ],
                  },
                },
              },
            ],
            as: 'userto',
          },
        },
        {
          $unwind: {
            path: '$userto',
            preserveNullAndEmptyArrays: true,
          },
        },
        {
          $lookup: {
            from: 'mygroups',
            let: { groupname: '$accto.groupname', idapp: '$accto.idapp' },
            pipeline: [
              {
                $match:
                {
                  $expr:
                  {
                    $and:
                      [
                        { $eq: ['$$groupname', '$groupname'] },
                        { $eq: ['$$idapp', '$idapp'] },
                      ],
                  },
                },
              },
            ],
            as: 'groupto',
          },
        },
        {
          $unwind: {
            path: '$groupto',
            preserveNullAndEmptyArrays: true,
          },
        },
        {
          $lookup: {
            from: 'circuits',
            let: { contocom: '$accto.contocom', idapp: '$accto.idapp' },
            pipeline: [
              {
                $match:
                {
                  $expr:
                  {
                    $and:
                      [
                        { $eq: ['$$contocom', '$path'] },
                        { $eq: ['$$idapp', '$idapp'] },
                      ],
                  },
                },
              },
            ],
            as: 'contocomto',
          },
        },
        {
          $unwind: {
            path: '$contocomto',
            preserveNullAndEmptyArrays: true,
          },
        },
        {
          $project:
          {
            transactionDate: 1,
            amount: 1,
            causal: 1,
            notifId: 1,
            'circuitfrom.symbol': 1,
            'circuitto.symbol': 1,
            'userfrom.username': 1,
            'userfrom.profile.img': 1,
            'userto.username': 1,
            'userto.profile.img': 1,
            'groupfrom.groupname': 1,
            'groupfrom.title': 1,
            'groupfrom.photos': 1,
            'groupto.groupname': 1,
            'groupto.title': 1,
            'groupto.photos': 1,
            'contocomfrom.path': 1,
            'contocomfrom.name': 1,
            'contocomto.path': 1,
            'contocomto.name': 1,
          },
        },

      ];

      return aggr1;
    }

  } catch (e) {
    return [];
  }

  return [];
};


MovementSchema.statics.getQueryAllUsersMovsByCircuitId = async function (idapp, circuitId) {

  try {
    if (!circuitId) {
      return [];
    }
    let aggr1 = [
      {
        $match: {
          idapp,
        },
      },
      {
        $lookup: {
          from: 'accounts',
          localField: 'accountFromId',
          foreignField: '_id',
          as: 'accfrom',
        },
      },
      { $unwind: '$accfrom' },
      {
        $lookup: {
          from: 'users',
          let: { username: '$accfrom.username', idapp: '$accfrom.idapp' },
          pipeline: [
            {
              $match:
              {
                $expr:
                {
                  $and:
                    [
                      { $eq: ['$$username', '$username'] },
                      { $eq: ['$$idapp', '$idapp'] },
                    ],
                },
              },
            },
          ],
          as: 'userfrom',
        },
      },
      {
        $unwind: {
          path: '$userfrom',
          preserveNullAndEmptyArrays: true,
        },
      },
      {
        $lookup: {
          from: 'mygroups',
          let: { groupname: '$accfrom.groupname', idapp: '$accfrom.idapp' },
          pipeline: [
            {
              $match:
              {
                $expr:
                {
                  $and:
                    [
                      { $eq: ['$$groupname', '$groupname'] },
                      { $eq: ['$$idapp', '$idapp'] },
                    ],
                },
              },
            },
          ],
          as: 'groupfrom',
        },
      },
      {
        $unwind: {
          path: '$groupfrom',
          preserveNullAndEmptyArrays: true,
        },
      },
      {
        $lookup: {
          from: 'circuits',
          let: { contocom: '$accfrom.contocom', idapp: '$accfrom.idapp' },
          pipeline: [
            {
              $match:
              {
                $expr:
                {
                  $and:
                    [
                      { $eq: ['$$contocom', '$path'] },
                      { $eq: ['$$idapp', '$idapp'] },
                    ],
                },
              },
            },
          ],
          as: 'contocomfrom',
        },
      },
      {
        $unwind: {
          path: '$contocomfrom',
          preserveNullAndEmptyArrays: true,
        },
      },
      {
        $lookup: {
          from: 'accounts',
          localField: 'accountToId',
          foreignField: '_id',
          as: 'accto',
        },
      },
      {
        $unwind: {
          path: '$accto',
          preserveNullAndEmptyArrays: true,
        },
      },
      {
        $match: { 'accto.circuitId': circuitId },
      },
      {
        '$lookup': {
          'from': 'circuits',
          'localField': 'accfrom.circuitId',
          'foreignField': '_id',
          'as': 'circuitfrom',
        },
      },
      {
        $unwind: {
          path: '$circuitfrom',
          preserveNullAndEmptyArrays: true,
        },
      },
      {
        '$lookup': {
          'from': 'circuits',
          'localField': 'accto.circuitId',
          'foreignField': '_id',
          'as': 'circuitto',
        },
      },
      {
        $unwind: {
          path: '$circuitto',
          preserveNullAndEmptyArrays: true,
        },
      },
      {
        $lookup: {
          from: 'users',
          let: { username: '$accto.username', idapp: '$accto.idapp' },
          pipeline: [
            {
              $match:
              {
                $expr:
                {
                  $and:
                    [
                      { $eq: ['$$username', '$username'] },
                      { $eq: ['$$idapp', '$idapp'] },
                    ],
                },
              },
            },
          ],
          as: 'userto',
        },
      },
      {
        $unwind: {
          path: '$userto',
          preserveNullAndEmptyArrays: true,
        },
      },
      {
        $lookup: {
          from: 'mygroups',
          let: { groupname: '$accto.groupname', idapp: '$accto.idapp' },
          pipeline: [
            {
              $match:
              {
                $expr:
                {
                  $and:
                    [
                      { $eq: ['$$groupname', '$groupname'] },
                      { $eq: ['$$idapp', '$idapp'] },
                    ],
                },
              },
            },
          ],
          as: 'groupto',
        },
      },
      {
        $unwind: {
          path: '$groupto',
          preserveNullAndEmptyArrays: true,
        },
      },
      {
        $lookup: {
          from: 'circuits',
          let: { contocom: '$accto.contocom', idapp: '$accto.idapp' },
          pipeline: [
            {
              $match:
              {
                $expr:
                {
                  $and:
                    [
                      { $eq: ['$$contocom', '$path'] },
                      { $eq: ['$$idapp', '$idapp'] },
                    ],
                },
              },
            },
          ],
          as: 'contocomto',
        },
      },
      {
        $unwind: {
          path: '$contocomto',
          preserveNullAndEmptyArrays: true,
        },
      },
      {
        $project:
        {
          transactionDate: 1,
          amount: 1,
          causal: 1,
          notifId: 1,
          'circuitfrom.symbol': 1,
          'circuitto.symbol': 1,
          'userfrom.username': 1,
          'userfrom.profile.img': 1,
          'userto.username': 1,
          'userto.profile.img': 1,
          'groupfrom.groupname': 1,
          'groupfrom.title': 1,
          'groupto.groupname': 1,
          'groupto.title': 1,
          'contocomfrom.path': 1,
          'contocomfrom.name': 1,
          'contocomfrom.title': 1,
          'contocomto.path': 1,
          'contocomto.name': 1,
          'contocomto.title': 1,
        },
      },

    ];

    return aggr1;

  } catch (e) {
    return [];
  }

  return [];
};

MovementSchema.statics.getMovsByCircuitId = async function (idapp, username, circuitId) {
  const MyMovement = this;

  const myquery = await MyMovement.getQueryMovsByCircuitId(idapp, username, '', '', circuitId);

  if (myquery && myquery.length > 0) {
    ris = await MyMovement.aggregate(myquery);

    return ris;
  }

  return [];
};

MovementSchema.statics.checkIfCoinsAlreadySent = async function (notifId) {
  const MyMovement = this;

  try {
    const rec = await MyMovement.findOne({ notifId }, { _id: 1 });
    return !!rec;

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

};


const Movement = mongoose.model('Movement', MovementSchema);

module.exports = { Movement };
