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 { Movement } = require('../models/movement');
const { Account } = require('../models/account');

const { Province } = require('../models/province');
const shared_consts = require('../tools/shared_nodejs');

const i18n = require('i18n');

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

const CircuitSchema = new Schema({
  _id: {
    type: String,
    default: function () {
      return new ObjectID().toString();
    },
  },
  idapp: {
    type: String,
    required: true,
  },
  groupnameId: {
    type: String,
  },
  name: {
    type: String,
    unique: true,
  },
  path: {
    type: String,
    unique: true,
  },
  link_group: {
    type: String,
  },
  subname: {
    type: String,
  },
  idCity: [
    {
      type: Number,
    }],
  strProv:
  {
    type: String,
  },
  card:  // Punti cardinali
  {
    type: String,
  },
  pub_to_share: {
    type: Number,  // PUB_TO_SHARE_ALL, PUB_TO_SHARE_ONLY_TABLE_FOLLOW
  },
  visibility: [
    {
      type: Number,
    },
  ],
  longdescr: {
    type: String,
  },
  regulation: {
    type: String,
  },
  systemUserDescr: {
    type: String,
  },
  systemUserId: {
    type: String,
  },
  totCircolante: {
    type: Number,
  },
  showAlways: {
    type: Boolean,
  },
  totTransato: {
    type: Number,
  },
  nome_valuta: {
    type: String,
    maxlength: 20,
  },
  symbol: {
    type: String,
    maxlength: 7,
  },
  color: {
    type: String,
  },
  abbrev: {
    type: String,
    maxlength: 7,
  },
  compara_valuta: {
    type: Number,
    default: 1,
  },
  compara_euro: {
    type: Number,
    default: 1,
  },
  valuta_per_euro: {
    type: Number,
    default: 1,
  },
  fido_scoperto_default: {
    type: Number,
  },
  qta_max_default: {
    type: Number,
  },
  fido_scoperto_default_grp: {
    type: Number,
  },
  qta_max_default_grp: {
    type: Number,
  },
  data_costituz: {
    type: Date,
  },
  deperimento: {
    type: Boolean,
  },
  freq_deper: {   // H, D, W, M, Y
    type: String,
  },
  minuto_deper: {
    type: Number,
  },
  ora_deper: {
    type: Number,
  },
  giorno_deper: {
    type: Number,
  },
  mese_deper: {
    type: Number,
  },
  ultimo_deper: {
    type: Date,
  },
  durata_deper: {
    type: Number,
  },
  // -------------
  createdBy: {
    type: String,
  },
  date_created: {
    type: Date,
  },
  date_updated: {
    type: Date,
  },
  admins: [
    {
      username: { type: String },
      date: { type: Date },
    },
  ],
  photos: [
    {
      imagefile: {
        type: String,
      },
      alt: {
        type: String,
      },
      description: {
        type: String,
      },
    }],
  req_users: [
    {
      _id: false,
      username: { type: String },
      date: { type: Date },
    }],  // username
  refused_users: [
    {
      _id: false,
      username: { type: String },
      date: { type: Date },
    }],  // username
  req_groups: [
    {
      _id: false,
      groupname: { type: String },
      date: { type: Date },
    }],  // username
  refused_groups: [
    {
      _id: false,
      groupname: { type: String },
      date: { type: Date },
    }],  // username
  deleted: {
    type: Boolean,
    default: false,
  },
  transactionsEnabled: {
    type: Boolean,
  },
  numMembers: {
    type: Number,
    default: 0,
  },
  showAlways: {
    type: Boolean,
    default: false,
  },
  status: {
    type: Number,
    default: 0,
  },
});

CircuitSchema.pre('save', async function (next) {
  if (this.isNew) {
    this._id = new ObjectID().toString();

    this.date_created = new Date();
  }

  next();
});

CircuitSchema.statics.findAllIdApp = async function (idapp) {
  const Circuit = this;

  const myfind = { idapp, deleted: false };

  const whatToShow = this.getWhatToShow(idapp, '');

  return await Circuit.find(myfind, whatToShow).sort({ status: -1, numMembers: -1, name: 1 });
};

CircuitSchema.statics.getFieldsForSearch = function () {
  return [
    { field: 'name', type: tools.FieldType.string },
    { field: 'subname', type: tools.FieldType.string },
    { field: 'path', type: tools.FieldType.string },
    { field: 'nome_valuta', type: tools.FieldType.string },
    { field: 'descr', type: tools.FieldType.string },
  ];
};

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

CircuitSchema.statics.getWhatToShow = function (idapp, username) {
  // FOR ME, PERMIT ALL
  return {
    _id: 1,
    groupnameId: 1,
    path: 1,
    name: 1,
    subname: 1,
    longdescr: 1,
    regulation: 1,
    numMembers: 1,
    totCircolante: 1,
    totTransato: 1,
    systemUserId: 1,
    createdBy: 1,
    date_created: 1,
    date_updated: 1,
    nome_valuta: 1,
    fido_scoperto_default: 1,
    qta_max_default: 1,
    fido_scoperto_default_grp: 1,
    qta_max_default_grp: 1,
    deperimento: 1,
    showAlways: 1,
    transactionsEnabled: 1,
    status: 1,
    valuta_per_euro: 1,
    symbol: 1,
    idCity: 1,
    strProv: 1,
    card: 1,
    link_group: 1,
    pub_to_share: 1,
    visibility: 1,
    color: 1,
    abbrev: 1,
    data_costituz: 1,
    photos: 1,
    admins: 1,
    req_users: 1,
    refused_users: 1,
    req_groups: 1,
    refused_groups: 1,
    'mycities': 1,
  };

};

// Aggiungi agli Admin del Circuito
CircuitSchema.statics.addToAdminOfMyCircuit = async function (idapp, username, name) {

  return await Circuit.updateOne({ idapp, name },
    {
      $push:
      {
        admins: {
          username,
          date: new Date(),
        },
      },
    });

};

// Rimuovi dagli Admin del Circuito
CircuitSchema.statics.removeAdminOfMyCircuit = async function (idapp, username, name) {

  return await Circuit.updateOne({ idapp, name },
    { $pull: { admins: { username: { $in: [username] } } } });
};

CircuitSchema.statics.getWhatToShow_Unknown = function (idapp, username) {
  return {
    groupnameId: 1,
    path: 1,
    name: 1,
    subname: 1,
    longdescr: 1,
    regulation: 1,
    numMembers: 1,
    showAlways: 1,
    systemUserId: 1,
    founderUserId: 1,
    nome_valuta: 1,
    totCircolante: 1,
    totTransato: 1,
    fido_scoperto_default: 1,
    fido_scoperto_default_grp: 1,
    qta_max_default_grp: 1,
    qta_max_default: 1,
    valuta_per_euro: 1,
    symbol: 1,
    color: 1,
    idCity: 1,
    strProv: 1,
    card: 1,
    link_group: 1,
    pub_to_share: 1,
    visibility: 1,
    abbrev: 1,
    data_costituz: 1,
    photos: 1,
    admins: 1,
    createdBy: 1,
    date_created: 1,
    date_updated: 1,
    req_users: 1,
    refused_users: 1,
    req_groups: 1,
    refused_groups: 1,
    transactionsEnabled: 1,
    status: 1,
    'mycities': 1,
  };
};

CircuitSchema.statics.getCircuitsByUsername = async function (idapp, username, user) {

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

    const whatToShow = this.getWhatToShow(idapp, username);
    const whatToShow_Unknown = this.getWhatToShow_Unknown(idapp, username);
    // const arrUsernameCircuits = await User.getUsernameCircuitsByUsername(idapp, username);
    // const arrUsernameReqCircuits = await MyCircuit.getUsernameReqCircuitsByCircuitname(idapp, username);

    const manage_mycircuits = await Circuit.find({
      idapp,
      'admins': {
        $elemMatch: { username: { $eq: username } },
      },
      $or: [
        { deleted: { $exists: false } },
        { deleted: { $exists: true, $eq: false } }],
    }).sort({ status: -1, numMembers: -1, name: 1 }).lean();

    let listcircuits = await Circuit.find({
      idapp,
      $or: [
        { deleted: { $exists: false } },
        { deleted: { $exists: true, $eq: false } }],
    }, whatToShow_Unknown).sort({ status: -1, numMembers: -1, name: 1 }).lean();

    let asked_circuits = await Circuit.find({
      idapp,
      'req_users': {
        $elemMatch: { username: { $eq: username } },
      },
      $or: [
        { deleted: { $exists: false } },
        { deleted: { $exists: true, $eq: false } }],
    }, whatToShow_Unknown).sort({ status: -1 }).lean();

    let refused_circuits = await Circuit.find({
      idapp,
      'refused_users': {
        $elemMatch: { username: { $eq: username } },
      },
      $or: [
        { deleted: { $exists: false } },
        { deleted: { $exists: true, $eq: false } }],
    }, whatToShow_Unknown).sort({ status: -1 }).lean();

    return {
      listcircuits,
      asked_circuits,
      refused_circuits,
      manage_mycircuits,
      mycircuits: user.profile.mycircuits,
    };

  } catch (e) {
    console.log('Error getCircuitsByUsername', e);
  }

  return {
    listUsersCircuit: [],
    listRequestUsersCircuit: [],
    listTrusted: [],
    asked_circuits: [],
    refused_circuits: [],

  };
};

CircuitSchema.statics.getInfoCircuitByName = async function (idapp, name) {

  const whatToShow = this.getWhatToShow(idapp, '');

  const myfind = {
    idapp,
    name,
  };

  try {
    return await Circuit.findOne(myfind, whatToShow).lean();

  } catch (e) {
    return null;
  }

};

CircuitSchema.statics.getCircuitByName = async function (idapp, name) {

  const myfind = {
    idapp,
    name,
  };

  try {
    return await Circuit.findOne(myfind);

  } catch (e) {
    return null;
  }

};

CircuitSchema.statics.getCircuitIdByName = async function (idapp, name) {

  const myfind = {
    idapp,
    name,
  };

  try {
    const circuit = await Circuit.findOne(myfind);
    return (!!circuit ? circuit._id : 0);

  } catch (e) {
    return null;
  }

};

CircuitSchema.statics.getCircuitByProvinceAndCard = async function (idapp, strProv, card) {

  let myfind = {};

  if (card) {
    myfind = {
      idapp,
      strProv,
      card
    };
  } else {
    myfind = {
      idapp,
      strProv,
    };
  }

  try {
    return await Circuit.findOne(myfind);

  } catch (e) {
    return null;
  }

};

CircuitSchema.statics.getCircuitById = async function (circuitId) {

  const myfind = {
    _id: circuitId,
  };

  try {
    return await Circuit.findOne(myfind);

  } catch (e) {
    return null;
  }

};

CircuitSchema.statics.deleteCircuit = async function (idapp, usernameOrig, name) {
  console.log('Circuito ' + name + ' rimosso da ' + usernameOrig);
  return await Circuit.findOneAndRemove({ idapp, name });
};


CircuitSchema.statics.getUsersSingleCircuit = async function (idapp, username, circuitname, circuitId) {

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

  try {
    let aggr1 = [
      {
        $match: {
          idapp: idapp,
          'profile.mycircuits': {
            $elemMatch: { circuitname: { $eq: circuitname } },
          },
        },
      },

      /*{
        $lookup: {
          from: 'circuits',
          as: 'circuit',
          let: {circuitname: circuitname, idapp: '$idapp'},
          pipeline: [
            {
              $match:
                  {
                    $expr:
                        {
                          $and:
                              [
                                {$eq: ['$name', '$$circuitname']},
                                {$eq: ['$idapp', '$$idapp']},

                              ],
                        },
                  },
            },
          ],
        },

      },
      {$unwind: '$circuit'},
       */
      {
        $project: {
          username: 1,
          name: 1,
          surname: 1,
          profile: 1,
          idapp: 1 /*, 'circuit.name': 1, 'circuit._id': 1*/
        },

      },
      {
        $lookup: {
          from: 'accounts',
          as: 'account',
          let: { username: '$username', idapp: '$idapp', circuitId: circuitId /*, circuitId: '$circuit._id' */ },
          pipeline: [
            {
              $match:
              {
                $expr:
                {
                  $and:
                    [
                      { $eq: ['$$username', '$username'] },
                      { $eq: ['$$idapp', '$idapp'] },
                      { $eq: ['$$circuitId', '$circuitId'] },
                    ],
                },
              },
            },
          ],
        },
      },
      { $unwind: '$account' },
    ];

    ris = await User.aggregate(aggr1);

    return ris;
  } catch (e) {
    console.error('e', e);
  }

};

CircuitSchema.statics.getCircolanteSingolaTransaz = function (accountorigTable, accountdestTable) {

  let circolante = 0;
  if (accountdestTable.saldo > 0)
    circolante += accountdestTable.saldo;
  if (accountorigTable.saldo > 0)
    circolante += accountorigTable.saldo;

  return circolante;
};

CircuitSchema.statics.sendCoins = async function (onlycheck, idapp, usernameOrig, extrarec) {

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

  let ris = {
    result: false,
    cansend: true,
    errormsg: '',
    rec: null,
    useraccounts: [],
  };

  try {
    let circuittable = null;
    if (extrarec.circuitname)
      circuittable = await Circuit.getCircuitByName(idapp, extrarec.circuitname);
    if (extrarec.circuitId)
      circuittable = await Circuit.getCircuitById(idapp, extrarec.circuitId);

    if (circuittable) {
      const myqty = Math.abs(extrarec.qty);

      const esisteDest = await Account.isExistAccountByUsernameAndCircuitId(idapp, extrarec.dest, circuittable._id, extrarec.groupdest, extrarec.contoComDest);

      if (!esisteDest) {
        // Fallo entrare anche sul Circuito (oltre ad aver creato l'Account).
        await User.addCircuitToUser(idapp, usernameOrig, extrarec.circuitname, false, extrarec.groupdest, extrarec.contoComDest);
      }
      if (extrarec.dest) {
        const foundIfAlreadyCircuit = await User.ifAlreadyInCircuit(idapp, extrarec.dest, extrarec.circuitname);
        if (!foundIfAlreadyCircuit) {
          update = {
            $push: {
              'profile.mycircuits': {
                circuitname: extrarec.circuitname,
                date: new Date(),
              },
            },
          };
          const ris = await User.updateOne({ idapp, username: extrarec.dest }, update);
        }
      }

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


      const circolantePrec = this.getCircolanteSingolaTransaz(accountorigTable, accountdestTable);

      // Check if Sender has enough money
      if (accountorigTable.saldo - myqty < -accountorigTable.fidoConcesso) {
        ris.cansend = false;
        ris.errormsg = i18n.__('CIRCUIT_AMOUNT_EXCEED_FIDO', usernameOrig);
      }

      if (accountdestTable.saldo + myqty > accountdestTable.qta_maxConcessa) {
        ris.cansend = false;
        ris.errormsg = i18n.__('CIRCUIT_AMOUNT_EXCEED_QTAMAX', extrarec.dest);
      }

      if (!onlycheck) {
        // Add a Transaction !
        if (ris.cansend) {
          ris.rec = await Movement.addMov(idapp, accountorigTable, accountdestTable, myqty, extrarec.causal, extrarec.notifId);
        }

        if (ris.cansend && ris.rec) {

          const circolanteAtt = this.getCircolanteSingolaTransaz(accountorigTable, accountdestTable);

          // Somma di tutte le transazioni
          circuittable.totTransato += myqty;
          // circuittable.totCircolante = circuittable.totCircolante + (circolanteAtt - circolantePrec);
          circuittable.totCircolante = await Account.calcTotCircolante(idapp, circuittable._id);
          // await circuittable.save();
          paramstoupdate = {
            totTransato: circuittable.totTransato,
            totCircolante: circuittable.totCircolante,
          };
          await Circuit.updateOne({ _id: circuittable }, { $set: paramstoupdate });

          extrarec.saldoOrig = accountorigTable.saldo;
          extrarec.saldoDest = accountdestTable.saldo;

          let orig = usernameOrig;
          if (extrarec.grouporig) {
            orig = extrarec.grouporig + ' (' + usernameOrig + ')'
          }
          if (extrarec.contoComOrig) {
            orig = extrarec.contoComOrig + ' (' + usernameOrig + ')'
          }
          let dest = (extrarec.dest ? extrarec.dest : '') + (extrarec.groupdest ? extrarec.groupdest : '') + (extrarec.contoComDest ? extrarec.contoComDest : '');

          ris.result = true;
          let msg = '[<b>' + circuittable.name + '</b>]: Inviate Monete da ' + orig + ' a ' + dest + ' ' + myqty + ' ' + circuittable.symbol + ' [causale: ' + extrarec.causal +
            `]\nSaldi:\n${orig}: ` + extrarec.saldoOrig + ' ' + circuittable.symbol + '] ' + `\n${dest}: ` + extrarec.saldoDest + ' ' + circuittable.symbol + ']';
          console.log(msg);

          ris.useraccounts = await Account.getUserAccounts(idapp, usernameOrig);

          tools.writeTransactionLog(msg);

          tools.sendMsgTelegramToAdmin(idapp, msg);

        } else {
          // console.log('NON Inviate Monete da', usernameOrig, extrarec.grouporig, extrarec.dest, extrarec.groupdest, myqty, extrarec.causal);
        }
      }

      return ris;

    }
  } catch (e) {
    console.error('Err sendCoins', e);
    ris.result = false;
    return ris;
  }

};

// Rimuovo la Richiesta del Circuito
CircuitSchema.statics.removeReqCircuit = async function (idapp, username, name) {

  return await Circuit.updateOne({ idapp, name },
    { $pull: { req_users: { username: { $in: [username] } } } });
};

// Rimuovo la Richiesta del Gruppo sul Circuito
CircuitSchema.statics.removeReqGroupCircuit = async function (idapp, groupname, name) {

  return await Circuit.updateOne({ idapp, name },
    { $pull: { req_groups: { groupname: { $in: [groupname] } } } });
};

// Aggiungi agli utenti Rifiutati del Circuito

CircuitSchema.statics.refuseReqCircuit = async function (idapp, username, name) {

  return await Circuit.updateOne({ idapp, name },
    {
      $push:
      {
        refused_users: {
          username,
          date: new Date(),
        },
      },
    });

};

CircuitSchema.statics.refuseReqGroupCircuit = async function (idapp, groupname, name) {

  return await Circuit.updateOne({ idapp, name },
    {
      $push:
      {
        refused_groups: {
          groupname,
          date: new Date(),
        },
      },
    });

};

CircuitSchema.statics.updateData = async function (idapp, circuitname) {

  try {

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

    let aggr1 = [
      {
        $match: {
          idapp,
          'profile.mycircuits': {
            $elemMatch: { circuitname: { $eq: circuitname } },
          },
        },
      },
      { $group: { _id: null, count: { $sum: 1 } } },
    ];

    const ris = await User.aggregate(aggr1);

    let numMembers = 0;
    try {
      numMembers = ris && tools.isArray(ris) ? ris[0].count : 0;
    } catch (e) {

    };


    let paramstoupdate = {
      numMembers: numMembers,
    };
    const risult = await this.updateOne({ idapp, name: circuitname }, { $set: paramstoupdate });

    console.log('risult', risult);

  } catch (e) {
    console.error('Err', e);
  }

};

CircuitSchema.statics.setDeperimentoOff = async function () {

  return await Circuit.updateMany({}, { $set: { 'deperimento': false } },
    { new: false });

};

CircuitSchema.statics.getNameByCircuitId = async function (circuitId) {

  let circuit = await Circuit.findOne({ _id: circuitId });
  if (circuit)
    return circuit.name;

  return '';

};

CircuitSchema.statics.getCircuitByCircuitId = async function (circuitId) {

  return await Circuit.findOne({ _id: circuitId });

};

CircuitSchema.statics.getListAdminsByCircuitPath = async function (idapp, circuitPath) {

  let arr = await Circuit.findOne({
    idapp,
    path: circuitPath,
    $or: [
      { deleted: { $exists: false } },
      { deleted: { $exists: true, $eq: false } }],
  }, { admins: 1 }).lean();

  return arr && arr.admins ? arr.admins : [];

};


// Imposta a tutti i Conti Collettivi, i seguenti minimi e massimi
CircuitSchema.statics.setstrProvByIdCityCircuits = async function (idapp) {
  const { City } = require('../models/city');

  const arrcircuits = await Circuit.find({ idapp }).lean();
  try {
    for (const rec of arrcircuits) {
      let recstrProv = await City.findOne({ _id: rec.idCity[0] });
      if (recstrProv) {
        let objProv = {}
        objProv['strProv'] = recstrProv.prov;
        await Circuit.updateOne({ _id: rec._id }, { $set: objProv });
      }
    }
  } catch (e) {

  }

};


CircuitSchema.statics.AbilitaTuttiCircuiti = async function (idapp) {

  const ris = await Circuit.updateMany({ idapp },
    {
      $set:
      {
        transactionsEnabled: true
      }
    });

  return ris;
};

CircuitSchema.statics.AzzeraRegolamentiTuttiCircuiti = async function (idapp) {

  const ris = await Circuit.updateMany({ idapp },
    {
      $set:
      {
        regulation: '',
      }
    });

  return ris;
};

// Imposta a tutti i Conti Personali, i seguenti minimi e massimi
CircuitSchema.statics.SetDefMinMaxPersonali = async function (idapp, valmin, valmax, circuitId) {

  if (circuitId) {
    const ris = await Circuit.updateOne({ _id: circuitId },
      {
        $set:
        {
          fido_scoperto_default: valmin,
          qta_max_default: valmax,
        }
      });
  } else {

    const ris = await Circuit.updateMany({ idapp },
      {
        $set:
        {
          fido_scoperto_default: valmin,
          qta_max_default: valmax,
        }
      });
  }

};

// Imposta a tutti i Conti Collettivi, i seguenti minimi e massimi
CircuitSchema.statics.getCircuitMyProvince = async function (idapp, username) {
  const { User } = require('../models/user');

  const myuser = await User.getUserByUsername(idapp, username);

  try {
    const circuit = await this.getCircuitByProvinceAndCard(idapp, myuser.profile.resid_province, myuser.profile.resid_card);

    if (circuit) {
      if (await User.ifAlreadyInCircuit(idapp, username, circuit.name)) {
        return circuit.name;
      }
    }

    return '[nessun Circuito]';

  } catch (e) {
    console.error('Error', e);
  }
};

// Imposta a tutti i Conti Collettivi, i seguenti minimi e massimi
CircuitSchema.statics.createCircuitIfNotExist = async function (req, idapp, province, card) {
  const { User } = require('../models/user');

  const useradmin = tools.USER_ADMIN_CIRCUITS;

  let myrec = null;
  try {
    const circuit = await this.getCircuitByProvinceAndCard(idapp, province, card);

    const nomeprovincia = await Province.getStrProvinceByProv(province);

    if (!circuit && nomeprovincia) {
      const circ = new Circuit({
        idapp,
        name: 'Circuito RIS ' + nomeprovincia,
        path: 'ris' + tools.convertSpaces_ToUScore(nomeprovincia.toLowerCase()),
        strProv: province,
        card,
        photos: [],
        color: '#ff5500',
        deperimento: false,
        showAlways: false,
        transactionsEnabled: true, // Abilita cmq il circuito dall'inizio
        status: shared_consts.CIRCUIT_STATUS.FASE1_CREAZIONE_GRUPPO,
        symbol: 'RIS',
        fido_scoperto_default: 100,
        qta_max_default: 200,
        fido_scoperto_default_grp: shared_consts.CIRCUIT_PARAMS.SCOPERTO_MIN_GRP,
        qta_max_default_grp: shared_consts.CIRCUIT_PARAMS.SCOPERTO_MAX_GRP,
        valuta_per_euro: 1,
        totTransato: 0,
        totCircolante: 0,
        date_created: new Date(),
        admins: [{ username: useradmin }],
      });

      myrec = await circ.save();

      if (myrec) {

        // nuovo Circuito:
        await User.setCircuitCmd(idapp, useradmin, myrec.name,
          shared_consts.CIRCUITCMD.CREATE, true, useradmin, myrec).then((ris) => {

          });

        // aggiungi il creatore al Circuito stesso
        await User.setCircuitCmd(idapp, useradmin, myrec.name,
          shared_consts.CIRCUITCMD.SET, true, useradmin, myrec).then((ris) => {

          });

      }

      msg = 'Nuovo Circuito Creato in Automatico: ' + myrec.name + ' (da ' + req.user.username + ')';
      tools.sendMsgTelegramToAdmin(idapp, msg);
    }
  } catch (e) {
    console.error('Error', e);
  }

  return myrec;

};

CircuitSchema.statics.getListAdmins = async function (idapp, circuitname) {

  let arr = await Circuit.findOne({
    idapp,
    name: circuitname,
    $or: [
      { deleted: { $exists: false } },
      { deleted: { $exists: true, $eq: false } }],
  }, { admins: 1 }).lean();

  let mystr = '';

  if (arr) {
    for (const admin of arr.admins) {
      mystr += await tools.getAhref(admin.username, await tools.getLinkUserTelegram(idapp, admin.username)) + ', ';
    }
  }

  return { str: mystr, num: arr ? arr.admins.length : 0 };

};

CircuitSchema.statics.isAdminCircuit = async function (idapp, circuitname, username) {

  let arr = await Circuit.findOne({
    idapp,
    name: circuitname,
    $or: [
      { deleted: { $exists: false } },
      { deleted: { $exists: true, $eq: false } }],
  }, { admins: 1 }).lean();

  if (arr) {
    for (const admin of arr.admins) {
      if (admin.username === username)
        return true;
    }
  }

  return false;

};

CircuitSchema.statics.getListCircuitsByUsername = async function (idapp, username, groupname) {

  let mystr = '';
  const { User } = require('../models/user');
  const myuser = await User.getUserByUsername(idapp, username);

  const useraccounts = await Account.getUserAccounts(idapp, username);
  const groupsaccounts = await Account.getGroupAccounts(idapp, groupname);



  for (let account of useraccounts) {
    if (myuser.profile.mycircuits.find((rec) => (rec.circuitname === account.circuit.name))) {
      if (account.groupname === '') {
        mystr += '\n👉🏻 ' + account.circuit.name + '\n';
        mystr += '   [Saldo: ' + account.saldo + ' RIS, ';
        mystr += ' Fido: ' + account.fidoConcesso + ' RIS, ';
        mystr += ' Transato: ' + account.totTransato + ' RIS]';
      }
    }
  }


  for (let account of groupsaccounts) {
    if (myuser.profile.mycircuits.find((rec) => (rec.circuitname === account.circuit.name))) {
      mystr += '\n GRUPPO: 👉🏻 <b>' + account.groupname + '</b> in ' + account.circuit.name + '\n';
      mystr += '   [Saldo: ' + account.saldo + ' RIS, ';
      mystr += ' Fido: ' + account.fidoConcesso + ' RIS, ';
      mystr += ' Transato: ' + account.totTransato + ' RIS]';
    }
  }

  if (!mystr) {
    mystr = '[Nessun Circuito]';
  }

  return mystr;

};

CircuitSchema.statics.SetDefMinMaxCollettivi = async function (idapp, valmin, valmax, circuitId) {

  if (circuitId) {
    const ris = await Circuit.updateOne({ _id: circuitId },
      {
        $set:
        {
          fido_scoperto_default_grp: valmin,
          qta_max_default_grp: valmax,
        }
      });
  } else {
    const ris = await Circuit.updateMany({ idapp },
      {
        $set:
        {
          fido_scoperto_default_grp: valmin,
          qta_max_default_grp: valmax,
        }
      });
  }

};


CircuitSchema.statics.setFido = async function (idapp, username, circuitName, groupname) {

  mycircuit = await Circuit.findOne({ idapp, name: circuitName });
  if (mycircuit) {
    const circuitId = mycircuit._id;
    let account = null;
    let fido = 0;
    let qtamax = 0;

    if (mycircuit.showAlways) {

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

      const myuser = await User.getUserByUsername(idapp, username);

      // Se è il circuito Nazionale, allora prende i valori dal proprio Circuito Locale:
      const accountsuser = await Account.getUserAccounts(idapp, username);
      if (accountsuser) {
        // Se lo trovo della mia provincia, prendo quello
        account = accountsuser.find((account) => account.circuit.strProv === myuser.profile.resid_province && account.circuit.card === myuser.profile.resid_card)
        if (!account && accountsuser.length > 0) {
          // Se non lo trovo, prendo il primo in cui sono entrato !
          account = accountsuser[0];
        }
        if (account && account.circuit) {
          if (groupname) {
            qtamax = account.circuit.qta_max_default_grp * shared_consts.CIRCUIT_CFG.MULT_FIDO_GROUP;
            fido = account.circuit.fido_scoperto_default_grp * shared_consts.CIRCUIT_CFG.MULT_FIDO_GROUP;
          } else {
            qtamax = account.circuit.qta_max_default * shared_consts.CIRCUIT_CFG.MULT_FIDO_USER;
            fido = account.circuit.fido_scoperto_default * shared_consts.CIRCUIT_CFG.MULT_FIDO_USER;
          }
        }
      } else {
        // Se non ho Circuiti locali, non applico il Fido !
        return false;
      }

    } else {
      account = await Account.getAccountByUsernameAndCircuitId(idapp, username, circuitId, true, true, groupname, '');
      if (groupname)
        fido = mycircuit.fido_scoperto_default_grp;
      else
        fido = mycircuit.fido_scoperto_default;
    }

    if (account) {
      if (qtamax > 0) {
        await Account.updateQtaMax(idapp, username, groupname, circuitId, qtamax);
      }

      const ris = await Account.updateFido(idapp, username, groupname, circuitId, fido);
      if (ris) {
        return { qta_maxConcessa: qtamax, fidoConcesso: fido };
      }
    }
  }
  return false;
};

const Circuit = mongoose.model('Circuit', CircuitSchema);

module.exports = { Circuit };
