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

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

const Gasordine = require('../models/gasordine');

const Order = require('../models/order');

class Cart {
  constructor(order, arrorders) {
    this.modify_at = new Date();

    this.items = {};
    if (!!order) {
      this.initializeFromOrder(order);
    } else if (!!arrorders) {
      for (const ord of arrorders) {
        this.items.push(ord)
      }
    }
    this.updatecarttotals(false);
  }

  initializeFromOrder(order) {
    this.idapp = order.idapp || 0;
    this.userId = order.userId || "";
    this.items[order._id] = order;
  }
  static constructByCart(cart) {
    try {
      const mynewcart = new Cart(null);
      mynewcart.idapp = cart.idapp || 0;
      mynewcart.items = cart.items;
      mynewcart.department = cart.department;
      mynewcart.userId = cart.userId || "";
      mynewcart.modify_at = new Date();
      mynewcart.note_ordine_gas = '';

      return mynewcart;
    } catch (e) {
      console.log('Error', e);
      return null;
    }
  }

  isAvailableByOrder(order) {
    if (order && order.product) {
      return (order.product.quantityAvailable > 0)
    }
    return false;
  }

  isInPreorderByOrder(order) {
    if (order && order.product) {
      return (order.product.bookableAvailableQty > 0)
    }
    return false;
  }

  isSameStorehouse(itemorder) {
    try {
      if (this.items.length > 0) {
        const mystorehouse = this.items[0].order.idStorehouse
        return (mystorehouse ? mystorehouse._id.toString() === itemorder.idStorehouse : true);
      } else {
        return true;
      }

    } catch (e) {
      return false;
    }
  }

  async addqty(itemorder) {

    const myitem = this.items.find((rec) => rec.order._id.toString() === itemorder._id)
    if (!!myitem) {
      let stepmin = myitem.order.product.minStepQty;
      let step = stepmin;
      if (this.isAvailableByOrder(myitem.order)) {
        if (myitem.order.quantity === 0)
          step = myitem.order.product.minBuyQty ?? stepmin
        else if (myitem.order.quantity >= 10)
          step = stepmin < 2 ? 2 : stepmin
        else if (myitem.order.quantity >= 20)
          step = stepmin < 5 ? 5 : stepmin

        myitem.order.quantity += step;
      } else {
        if (myitem.order.quantitypreordered === 0)
          step = myitem.order.product.minBuyQty ?? stepmin
        else if (myitem.order.quantitypreordered >= 10)
          step = stepmin < 2 ? 2 : stepmin
        else if (myitem.order.quantitypreordered >= 20)
          step = stepmin < 5 ? 5 : stepmin

        myitem.order.quantitypreordered += step;
      }

      myitem.order.modify_at = new Date();

      myitem.order = Order.updateTotals(myitem.order);

      this.updatecarttotals(false);
      await this.updateExtraOrder();
      await Order.findOneAndUpdate({ _id: myitem.order._id }, { $set: myitem.order }, { new: false });
      return myitem.order;
    }
  }

  qtaNextSub(myorder, myproduct) {
    let step = myproduct.minStepQty
    let minqta = myproduct.minBuyQty
    if (myproduct.quantityAvailable > 0) {
      if (myorder.quantity === minqta)
        step = minqta
      else {
        if ((myorder.quantity - step) < 0)
          step = myorder.quantity - step
      }
    } else {
      if (myorder.quantitypreordered === minqta)
        step = minqta
    }

    return step
  }


  async subqty(itemorder) {
    try {
      const myitem = this.items.find((rec) => rec.order._id.toString() === itemorder._id)
      if (!!myitem) {
        let step = this.qtaNextSub(myitem.order, myitem.order.product);
        if (myitem.order.quantitypreordered - step >= 0) {
          myitem.order.quantitypreordered -= step;
        } else {
          if (myitem.order.quantity - step >= 0) {
            myitem.order.quantity -= step;
          }
        }
        myitem.order = Order.updateTotals(myitem.order);
        this.updatecarttotals(false);
        await this.updateExtraOrder();

        await Order.findOneAndUpdate({ _id: myitem.order._id }, { $set: myitem.order }, { new: false });
        return myitem.order;
      }
    } catch (e) {
      console.error('Err: ', e);
    }
  }


  async addItem(itemorder) {
    // this.items.push(itemorder);

    let ind = this.items.length;
    this.items[ind] = {};
    this.items[ind].order = itemorder;
    this.items[ind].order = Order.updateTotals(this.items[ind].order);
    this.updatecarttotals(false);
    await this.updateExtraOrder();

    return ind;
  }

  async removeItem(orderId) {
    // this.items.push(itemorder);
    this.items = this.items.filter(item => item.order._id.toString() !== orderId.toString());
    this.updatecarttotals(false);
    await this.updateExtraOrder();
  }

  generateModel() {
    try {
      let newCart = new cartModel({
        idapp: this.idapp,
        items: this.generateArray(),
        totalQty: this.totalQty,
        totalPriceCalc: this.totalPriceCalc,
        totalPrice: this.totalPrice,
        userId: this.userId,
        department: this.department,
        note: this.note,
        note_ordine_gas: this.note_ordine_gas,
        modify_at: this.modify_at
      })
      return newCart
    } catch (e) {
      console.error('Err', e);
    }
    return null;
  }

  updatecarttotals(updatecalcprice) {
    try {
      this.totalQty = 0;
      this.totalPrice = 0;
      this.totalPriceCalc = 0;
      for (const rec in this.items) {
        let mypricecalc = 0;

        let order = this.items[rec].order;
        if (!order) {
          order = this.items[rec];
        }
        order.TotalPriceProductCalc = 0;
        if (updatecalcprice) {
          order.TotalPriceProduct = 0;
        }
        this.totalQty += order.quantity + order.quantitypreordered;

        // Calcolo Sconto
        let sconti_da_applicare = [];
        if (order.scontisticas) {

          let qtadascontare = order.quantity + order.quantitypreordered
          let qtanonscontata = 0

          while (qtadascontare > 0) {
            let scontoapplicato = null
            for (const sconto of order.scontisticas.filter((rec) => !rec.cumulativo)) {
              if (qtadascontare >= sconto.qta) {
                scontoapplicato = sconto
                scontoapplicato.qtadascontare = sconto.qta
              }
            }
            if (scontoapplicato && scontoapplicato.qtadascontare > 0) {
              sconti_da_applicare.push(scontoapplicato)
              qtadascontare -= scontoapplicato.qtadascontare
            } else {
              qtanonscontata = qtadascontare
              qtadascontare = 0
            }
          }

          /*for (const sconto of order.scontisticas.filter((rec) => rec.cumulativo)) {
            if ((sconto.qta % order.quantity) === 0) {
              sconti_da_applicare.push(sconto)
            }
          }*/

          if (sconti_da_applicare.length > 0) {
            for (const sconto of sconti_da_applicare) {
              if (sconto.perc_sconto > 0) {
                mypricecalc += (sconto.qtadascontare * order.price) * (1 - (sconto.perc_sconto / 100))
              } else {
                mypricecalc += sconto.price
              }
            }
          }
          if (qtanonscontata > 0) {
            mypricecalc += order.price * qtanonscontata;
          }
        } else {
          mypricecalc = (order.price * order.quantity) + (order.price * order.quantitypreordered);

        }
        // Aggiorna Totali 
        order.TotalPriceProductCalc += mypricecalc;
        if (updatecalcprice) {
          order.TotalPriceProduct += mypricecalc;
          order.TotalPriceProductstr = parseFloat(order.TotalPriceProduct.toFixed(2));
        }

        // Qui lo calcolo sempre, anche se lo cambio manualmente
        this.totalPriceCalc += mypricecalc;

        this.totalPrice += order.TotalPriceProduct;
      }
      this.totalPrice = parseFloat(this.totalPrice.toFixed(2))
      this.totalPriceCalc = parseFloat(this.totalPriceCalc.toFixed(2))

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

  }

  async updateExtraOrder() {
    try {

      let arrGas = [];
      const precnoteordgas = this.note_ordine_gas
      this.note_ordine_gas = '';
      for (const rec in this.items) {        
        let order = this.items[rec].order;
        if (!order) {
          order = this.items[rec];
        }
        // Prendo la nota valida e la metto visibile sul Carrello !
        if (order.idGasordine) {
          const recGas = await Gasordine.findOne({ _id: order.idGasordine }).lean();
          if (recGas) {
            if (recGas.note_ordine_gas) {
              if (!arrGas.includes(recGas._id.toString())) {
                if (this.note_ordine_gas)
                  this.note_ordine_gas += '<br>'

                this.note_ordine_gas += '<strong>' + recGas.name + '</strong>' + ':<br>' + recGas.note_ordine_gas;
                arrGas.push(recGas._id.toString());
              }
            }
          }
        }
      }

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

  generateArray() {
    let arr = [];
    for (let id in this.items) {
      arr.push(this.items[id])
    }
    return arr;
  }
}

module.exports = Cart
