import mongoose from 'mongoose';
import { generateId } from '../../utils.js';
const { Schema } = mongoose;
import { purchaseOrderModel } from './purchaseorder.schema.js';
import { taxRateModel } from '../management/taxrate.schema.js';
import { aggregateRollups, editObject, getObject } from '../../database.js';

const shipmentSchema = new Schema(
  {
    _reference: { type: String, default: () => generateId()() },
    orderType: { type: String, required: true },
    order: { type: Schema.Types.ObjectId, refPath: 'orderType', required: true },
    courierService: { type: Schema.Types.ObjectId, ref: 'courierService', required: false },
    trackingNumber: { type: String, required: false },
    amount: { type: Number, required: true },
    amountWithTax: { type: Number, required: true },
    taxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
    shippedAt: { type: Date, required: false },
    expectedAt: { type: Date, required: false },
    deliveredAt: { type: Date, required: false },
    cancelledAt: { type: Date, required: false },
    state: {
      type: {
        type: String,
        required: true,
      },
    },
  },
  { timestamps: true }
);

shipmentSchema.statics.recalculate = async function (shipment, user) {
  // Only purchase orders are supported for now
  if (shipment.orderType !== 'purchaseOrder') {
    return;
  }

  const orderId = shipment.order?._id || shipment.order;
  if (!orderId) {
    return;
  }

  var taxRate = shipment.taxRate;

  if (shipment.taxRate?._id && Object.keys(shipment.taxRate).length == 1) {
    taxRate = await getObject({
      model: taxRateModel,
      id: shipment.taxRate._id,
      cached: true,
    });
  }

  const amountWithTax = shipment.amount * (1 + (taxRate?.rate || 0) / 100);
  await editObject({
    model: shipmentModel,
    id: shipment._id,
    updateData: {
      amountWithTax: amountWithTax,
    },
    user,
    recalculate: false,
  });

  const rollupResults = await aggregateRollups({
    model: this,
    baseFilter: {
      order: new mongoose.Types.ObjectId(orderId),
      orderType: shipment.orderType,
    },
    rollupConfigs: [
      {
        name: 'shipmentTotals',
        rollups: [
          { name: 'amount', property: 'amount', operation: 'sum' },
          { name: 'amountWithTax', property: 'amountWithTax', operation: 'sum' },
        ],
      },
    ],
  });

  const totals = rollupResults.shipmentTotals || {};
  const totalShippingAmount = totals.amount.sum?.toFixed(2) || 0;
  const totalShippingAmountWithTax = totals.amountWithTax.sum?.toFixed(2) || 0;

  const purchaseOrder = await getObject({
    model: purchaseOrderModel,
    id: orderId,
    cached: true,
  });

  const grandTotalAmount =
    parseFloat(purchaseOrder.totalAmountWithTax || 0) + parseFloat(totalShippingAmountWithTax || 0);
  await editObject({
    model: purchaseOrderModel,
    id: orderId,
    updateData: {
      shippingAmount: parseFloat(totalShippingAmount).toFixed(2),
      shippingAmountWithTax: parseFloat(totalShippingAmountWithTax).toFixed(2),
      grandTotalAmount: parseFloat(grandTotalAmount).toFixed(2),
    },
    user,
    recalculate: false,
  });
};

// Add virtual id getter
shipmentSchema.virtual('id').get(function () {
  return this._id;
});

// Configure JSON serialization to include virtuals
shipmentSchema.set('toJSON', { virtuals: true });

// Create and export the model
export const shipmentModel = mongoose.model('shipment', shipmentSchema);
