const bcrypt = require('bcryptjs');
const mongoose = require('mongoose').set('debug', false)
const validator = require('validator');
const jwt = require('jsonwebtoken');
const _ = require('lodash');

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

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

const { Settings } = require('./settings');

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

mongoose.Promise = global.Promise;

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

mongoose.set('debug', false);

const GraduatoriaSchema = new mongoose.Schema({
  idapp: {
    type: String,
    required: true,
  },
  index: {
    type: Number,
  },
  idListaIngresso: {
    type: String,
  },
  ind_order: {
    type: Number,
  },
  num_tess: {
    type: Number,
  },
  ind: {
    type: Number,
  },
  // USER:
  username: {
    type: String,
  },
  name: {
    type: String,
  },
  surname: {
    type: String,
  },
  indimbarco: {
    type: Number,
  },
  numNaviEntrato: {  // Numero dell'Imbarco attuale
    type: Number,
  },
  numinvitati: {
    type: Number,
  },
  numinvitatiattivi: {
    type: Number,
  },
  numinvitatiTot: {
    type: Number,
  },
  numinvitatiattiviTot: {
    type: Number,
  },
  punteggio: {
    type: Number,
  },
  invitante_username: {
    type: String,
  },
  navestr: {
    type: String,
  },
  note: {
    type: String,
  },
  date_added: {  // Data d'Ingresso (Completato i Requisiti o premuto Bottone Magico)
    type: Date,
  },

});

GraduatoriaSchema.pre('save', async function (next) {
  if (this.isNew) {
    try {
      if (!this.index) {
        const myrec = await Graduatoria.findOne({ idapp: this.idapp }).limit(1).sort({ index: -1 });

        if (!!myrec) {
          this.index = myrec._doc.index + 1;
        } else {
          this.index = 1;
        }
      }
    } catch (e) {
      this.index = 2;
    }
  }

  next();
});


GraduatoriaSchema.statics.findByIndOrder = function (idapp, ind_order) {
  const Graduatoria = this;

  try {
    return Graduatoria.findOne({
      'idapp': idapp,
      'ind_order': ind_order,
    });
  } catch (e) {

  }
};

GraduatoriaSchema.statics.findByAllRecByUsername = function (idapp, username) {
  const Graduatoria = this;

  try {
    return Graduatoria.find({
      idapp,
      username,
    });
  } catch (e) {

  }
};

GraduatoriaSchema.statics.getNumDaImbarcare = async function (idapp) {
  const Graduatoria = this;

  return await Graduatoria. countDocuments({ idapp })

};

GraduatoriaSchema.statics.AggiornaIndiceGraduatoria = async function (idapp) {
  const Graduatoria = this;

  let index = 1;

  await Graduatoria.find({ idapp }).sort({ punteggio: -1, date_added: 1 }).then(async (arrrec) => {

    for (const rec of arrrec) {

      await Graduatoria.findOneAndUpdate({ _id: rec._id }, { $set: { index } }, { new: false });
      index++;
    }
  });

  return index - 1;

};

GraduatoriaSchema.statics.getLastImbarco = async function (idapp, username) {
  const Graduatoria = this;

  return await Graduatoria.findOne({ idapp, username }).sort({ _id: -1 });

};

GraduatoriaSchema.statics.getFirstUserGradFree = async function (idapp) {
  const Graduatoria = this;

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

  const arrrecgrad = await Graduatoria.find({ idapp, ind_order: { $gt: 0 } }).sort({ index: 1 }).limit(20);
  if (!!arrrecgrad) {
    for (const recgrad of arrrecgrad) {
      const myuser = await User.findOne({
        idapp,
        username: recgrad.username,
        $or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }]
      });

      if (!!myuser) {
        return recgrad;
      }
    }
  }

  return null;

};

/*
GraduatoriaSchema.statics.addSingoloInGraduatoria_InFondo = async function (idapp, recingr) {
  const Graduatoria = this;

  const lastimbarco = await Graduatoria.getLastImbarco(idapp, recingr.username);

  const arrindex = [];

  if (!!lastimbarco) {
    arrindex[recingr.username] = lastimbarco.indimbarco;
  } else {
    arrindex[recingr.username] = 1;
  }

  const newingr = await ListaIngresso.aggiornaRecListaIngr(idapp, recingr, arrindex);

  const myrectoadd = addRecGraduatoria(idapp, newingr, 100000);

  return await myrectoadd.save(myrectoadd)
    .then((ris) => {
      return !!ris;
    })
    .catch((e) => {
      console.error(e.message);
    });


};

 */

function addRecGraduatoria(idapp, ingr, index) {

  try {
    let rec = new Graduatoria({
      _id: new ObjectId(),
      idapp,
      idListaIngresso: ingr._id,
      ind_order: ingr.ind_order,
      num_tess: ingr.num_tess,
      username: ingr.username,
      name: ingr.name,
      surname: ingr.surname,
      indimbarco: ingr.indimbarco,
      numNaviEntrato: ingr.numNaviEntrato,
      numinvitati: ingr.numinvitati,
      numinvitatiattivi: ingr.numinvitatiattivi,
      numinvitatiTot: ingr.numinvitatiTot,
      numinvitatiattiviTot: ingr.numinvitatiattiviTot,
      punteggio: ingr.punteggio,
      invitante_username: ingr.invitante_username,
      navestr: ingr.navestr,
      note: ingr.note,
      date_added: ingr.date_added,
    });

    if (!!index) {
      rec.index = index;
    }
    return rec;
  } catch (e) {
    console.error(e.message);
    return null;
  }

}

GraduatoriaSchema.statics.addArrayInGraduatoria = async function (idapp, arrayingr) {
  const Graduatoria = this;

  try {
    let myobjadd = [];

    let index = 0;

    for (const ingr of arrayingr) {

      index++;

      myobjadd.push(addRecGraduatoria(idapp, ingr, index));
    }

    // Cancella prima tutto
    await Graduatoria.deleteMany({ idapp });

    // Riscrivi Tutto
    const ris = await Graduatoria.insertMany(myobjadd);


    if (!!ris)
      return ris.length;
    else
      return 0;

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

GraduatoriaSchema.statics.getFieldsForSearch = function () {
  return [
    { field: 'index', type: tools.FieldType.number },
    { field: 'ind_order', type: tools.FieldType.number },
    { field: 'name', type: tools.FieldType.string },
    { field: 'surname', type: tools.FieldType.string },
    { field: 'username', type: tools.FieldType.string },
    { field: 'invitante_username', type: tools.FieldType.string },
  ]
};

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

GraduatoriaSchema.statics.findAllIdApp = async function (idapp) {
  const Graduatoria = this;

  const myfind = { idapp };

  return await Graduatoria.find(myfind).lean();
};

GraduatoriaSchema.statics.isWorking = function (idapp) {

  return Settings.getValDbSettings(idapp, 'GRAD_WORK', false);

};

GraduatoriaSchema.statics.isUpdating = function (idapp) {

  return Settings.getValDbSettings(idapp, tools.UPDATE_GRADUATORIA, false);

};

GraduatoriaSchema.statics.setWorking = function (idapp, stato) {

  return Settings.setBool(idapp, 'GRAD_WORK', stato);

};

GraduatoriaSchema.statics.setGradUpdating = function (idapp, stato) {

  return Settings.setBool(idapp, tools.UPDATE_GRADUATORIA, stato);

};

function getinvit(index, myrec) {
  let inv = myrec.numinvitati;
  let invattivi = myrec.numinvitatiattivi;

  const step = (myrec.numNaviEntrato + index) * 2;

  inv -= step;
  // console.log('inv', inv, 'step = ', step)
  invattivi -= step;
  if (inv < 0)
    inv = 0;
  if (invattivi < 0)
    invattivi = 0;
  if (inv > 2)
    inv = 2;
  if (invattivi > 2)
    invattivi = 2;

  return { invattivi, inv }
}

/*
function getnuminv(index, myrec) {
  const ris = getinvit(index, myrec);

  return ris.inv
}

function getnuminvattivi(index, myrec) {
  const ris = getinvit(index, myrec);

  return ris.invattivi
}*/


GraduatoriaSchema.statics.getPosizioneInGraduatoria = async function (idapp, ind_order, username, num_tess) {
  const Graduatoria = this;

  const totposiz = await Graduatoria.countDocuments({ idapp });

  return await Graduatoria.findOne({ idapp, username, ind_order, num_tess }).then((rec) => {

    if (!!rec) {

    } else {
      return {
        posiz: 0,
        totposiz: 0,
        num_tess: 0,
        numinvitatiTot: 0,
        numinvitatiattiviTot: 0,
        numNaviEntrato: 0,
        indimbarco: 1,
      }
    }

    const ris = {
      totposiz,
      posiz: rec.index,
      numinvitatiTot: rec.numinvitatiTot,
      numinvitatiattiviTot: rec.numinvitatiattiviTot,
      num_tess: rec.num_tess,
      numNaviEntrato: rec.numNaviEntrato,
      indimbarco: rec.indimbarco,
    };

    return ris;
  });

};


const Graduatoria = mongoose.model('Graduatoria', GraduatoriaSchema);

Graduatoria.createIndexes()
  .then(() => { })
  .catch((err) => { throw err; });


module.exports = { Graduatoria };
