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

const orderItemSchema = new Schema(
  {
    _reference: { type: String, default: () => generateId()() },
    orderType: { type: String, required: true },
    state: {
      type: { type: String, required: true, default: 'draft' },
    },
    order: { type: Schema.Types.ObjectId, refPath: 'orderType', required: true },
    itemType: { type: String, required: true },
    item: { type: Schema.Types.ObjectId, refPath: 'itemType', required: true },
    syncAmount: { type: String, required: false, default: null },
    itemAmount: { type: Number, required: true },
    quantity: { type: Number, required: true },
    totalAmount: { type: Number, required: true },
    taxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
    totalAmountWithTax: { type: Number, required: true },
    timestamp: { type: Date, default: Date.now },
    shipment: { type: Schema.Types.ObjectId, ref: 'shipment', required: false },
    orderedAt: { type: Date, required: false },
    receivedAt: { type: Date, required: false },
  },
  { timestamps: true }
);

const rollupConfigs = [
  {
    name: 'shipped',
    filter: { 'state.type': 'shipped' },
    rollups: [{ name: 'shipped', property: 'state.type', operation: 'count' }],
  },
  {
    name: 'received',
    filter: { 'state.type': 'received' },
    rollups: [{ name: 'received', property: 'state.type', operation: 'count' }],
  },
];

orderItemSchema.statics.stats = async function () {
  const results = await aggregateRollups({
    model: this,
    baseFilter: {},
    rollupConfigs: rollupConfigs,
  });

  console.log(results);

  // Transform the results to match the expected format
  return results;
};

orderItemSchema.statics.history = async function (from, to) {
  const results = await aggregateRollupsHistory({
    model: this,
    startDate: from,
    endDate: to,
    rollupConfigs: rollupConfigs,
  });

  // Return time-series data array
  return results;
};

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

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

  var taxRate = orderItem.taxRate;

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

  const orderTotalAmount = orderItem.itemAmount * orderItem.quantity;
  const orderTotalAmountWithTax = orderTotalAmount * (1 + (taxRate?.rate || 0) / 100);
  await editObject({
    model: orderItemModel,
    id: orderItem._id,
    updateData: {
      totalAmount: orderTotalAmount,
      totalAmountWithTax: orderTotalAmountWithTax,
    },
    user,
    recalculate: false,
  });

  const rollupResults = await aggregateRollups({
    model: this,
    baseFilter: {
      order: new mongoose.Types.ObjectId(orderId),
      orderType: orderItem.orderType,
    },
    rollupConfigs: [
      {
        name: 'orderTotals',
        rollups: [
          { name: 'totalAmount', property: 'totalAmount', operation: 'sum' },
          {
            name: 'totalAmountWithTax',
            property: 'totalAmountWithTax',
            operation: 'sum',
          },
        ],
      },
      {
        name: 'overallCount',
        rollups: [{ name: 'overallCount', property: '_id', operation: 'count' }],
      },
      ...rollupConfigs,
    ],
  });

  console.log('rollupResults', rollupResults);

  const totals = rollupResults.orderTotals || {};
  const totalAmount = totals.totalAmount.sum?.toFixed(2) || 0;
  const totalAmountWithTax = totals.totalAmountWithTax.sum?.toFixed(2) || 0;

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

  const grandTotalAmount =
    parseFloat(totalAmountWithTax || 0) + parseFloat(purchaseOrder.shippingAmountWithTax || 0);

  var updateData = {
    totalAmount: parseFloat(totalAmount).toFixed(2),
    totalAmountWithTax: parseFloat(totalAmountWithTax).toFixed(2),
    totalTaxAmount: parseFloat((totalAmountWithTax - totalAmount).toFixed(2)),
    grandTotalAmount: parseFloat(grandTotalAmount).toFixed(2),
  };

  const overallCount = rollupResults.overallCount.count || 0;
  const shippedCount = rollupResults.shipped.count || 0;
  const receivedCount = rollupResults.received.count || 0;

  if (shippedCount > 0 && shippedCount < overallCount) {
    updateData = { ...updateData, state: { type: 'partiallyShipped' } };
  }

  if (shippedCount > 0 && shippedCount == overallCount) {
    updateData = { ...updateData, state: { type: 'shipped' } };
  }

  if (receivedCount > 0 && receivedCount < overallCount) {
    updateData = { ...updateData, state: { type: 'partiallyReceived' } };
  }

  if (receivedCount > 0 && receivedCount == overallCount) {
    updateData = { ...updateData, state: { type: 'received' } };
  }

  await editObject({
    model: purchaseOrderModel,
    id: orderId,
    updateData: updateData,
    user,
  });
};

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

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

// Create and export the model
export const orderItemModel = mongoose.model('orderItem', orderItemSchema);
