const mongoose = require('mongoose');
const { Schema } = mongoose;

const cartItemSchema = new Schema({
  item: {
    type: Schema.Types.ObjectId,
    ref: 'Item',
    required: true
  },
  quantity: {
    type: Number,
    required: true,
    min: 1,
    default: 1
  },
  price: {
    type: Number,
    required: true
  },
  total: {
    type: Number,
    required: true
  },
  prescriptionRequired: {
    type: Boolean,
    default: false
  },
  prescription: {
    type: Schema.Types.ObjectId,
    ref: 'Prescription'
  }
}, { _id: false });

const cartSchema = new Schema({
  user: {
    type: Schema.Types.ObjectId,
    ref: 'User',
    required: true,
    unique: true
  },
  items: [cartItemSchema],
  subtotal: {
    type: Number,
    default: 0
  },
  tax: {
    type: Number,
    default: 0
  },
  deliveryCharge: {
    type: Number,
    default: 0
  },
  total: {
    type: Number,
    default: 0
  },
  discount: {
    type: Number,
    default: 0
  },
  coupon: {
    type: Schema.Types.ObjectId,
    ref: 'Coupon'
  },
  createdAt: {
    type: Date,
    default: Date.now
  },
  updatedAt: {
    type: Date,
    default: Date.now
  }
}, {
  timestamps: true,
  toJSON: { virtuals: true },
  toObject: { virtuals: true }
});

// Calculate totals before saving
cartSchema.pre('save', function(next) {
  this.updatedAt = Date.now();
  
  // Calculate item totals
  this.items.forEach(item => {
    item.total = item.quantity * item.price;
  });
  
  // Calculate subtotal (sum of all item totals)
  this.subtotal = this.items.reduce((sum, item) => sum + item.total, 0);
  
  // Calculate total (subtotal + tax + delivery - discount)
  this.total = this.subtotal + this.tax + this.deliveryCharge - this.discount;
  
  next();
});

// Static method to get cart by user ID
cartSchema.statics.findByUserId = async function(userId) {
  return this.findOne({ user: userId })
    .populate('items.item', 'name price image discountPrice stock')
    .populate('coupon', 'code discountType discountValue');
};

// Instance method to add item to cart
cartSchema.methods.addItem = async function(itemData) {
  const { item: itemId, quantity, price, prescriptionRequired, prescription } = itemData;
  
  // Check if item already exists in cart
  const existingItemIndex = this.items.findIndex(
    cartItem => cartItem.item.toString() === itemId.toString()
  );

  if (existingItemIndex > -1) {
    // Update quantity if item exists
    this.items[existingItemIndex].quantity += quantity || 1;
    this.items[existingItemIndex].price = price || this.items[existingItemIndex].price;
    if (prescription) {
      this.items[existingItemIndex].prescription = prescription;
      this.items[existingItemIndex].prescriptionRequired = prescriptionRequired || false;
    }
  } else {
    // Add new item
    this.items.push({
      item: itemId,
      quantity: quantity || 1,
      price,
      prescriptionRequired: prescriptionRequired || false,
      prescription: prescription || null
    });
  }

  return this.save();
};

// Instance method to remove item from cart
cartSchema.methods.removeItem = async function(itemId) {
  this.items = this.items.filter(
    item => item.item.toString() !== itemId.toString()
  );
  
  return this.save();
};

// Instance method to update item quantity
cartSchema.methods.updateItemQuantity = async function(itemId, quantity) {
  const item = this.items.find(
    item => item.item.toString() === itemId.toString()
  );
  
  if (item) {
    item.quantity = quantity;
    return this.save();
  }
  
  return this;
};

// Instance method to clear cart
cartSchema.methods.clearCart = async function() {
  this.items = [];
  this.subtotal = 0;
  this.tax = 0;
  this.deliveryCharge = 0;
  this.discount = 0;
  this.total = 0;
  this.coupon = null;
  
  return this.save();
};

// Instance method to apply coupon
cartSchema.methods.applyCoupon = async function(coupon) {
  this.coupon = coupon._id;
  
  // Calculate discount based on coupon type
  if (coupon.discountType === 'percentage') {
    this.discount = (this.subtotal * coupon.discountValue) / 100;
  } else {
    this.discount = coupon.discountValue;
  }
  
  // Ensure discount doesn't exceed subtotal
  if (this.discount > this.subtotal) {
    this.discount = this.subtotal;
  }
  
  // Recalculate total
  this.total = this.subtotal + this.tax + this.deliveryCharge - this.discount;
  
  return this.save();
};

// Instance method to remove coupon
cartSchema.methods.removeCoupon = async function() {
  this.coupon = undefined;
  this.discount = 0;
  
  // Recalculate total
  this.total = this.subtotal + this.tax + this.deliveryCharge;
  
  return this.save();
};

// Add static method to initialize cart for a new user
cartSchema.statics.init = function() {
  if (mongoose.models.Cart) {
    return mongoose.models.Cart;
  }
  return this.model('Cart', cartSchema);
};

// Create and export the model
const Cart = mongoose.models.Cart || mongoose.model('Cart', cartSchema);
module.exports = Cart;
