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

const couponSchema = new Schema({
  code: {
    type: String,
    required: [true, 'Coupon code is required'],
    unique: true,
    trim: true,
    uppercase: true
  },
  description: {
    type: String,
    trim: true
  },
  discountType: {
    type: String,
    required: [true, 'Discount type is required'],
    enum: {
      values: ['percentage', 'fixed'],
      message: 'Discount type must be either "percentage" or "fixed"'
    }
  },
  discountValue: {
    type: Number,
    required: [true, 'Discount value is required'],
    min: [0, 'Discount value cannot be negative'],
    validate: {
      validator: function(value) {
        if (this.discountType === 'percentage') {
          return value >= 0 && value <= 100;
        }
        return value > 0;
      },
      message: 'Percentage discount must be between 0-100, fixed discount must be greater than 0'
    }
  },
  minOrderAmount: {
    type: Number,
    default: 0,
    min: [0, 'Minimum order amount cannot be negative']
  },
  maxDiscountAmount: {
    type: Number,
    default: null,
    validate: {
      validator: function(value) {
        if (this.discountType === 'percentage' && value === null) {
          return false;
        }
        return value === null || value > 0;
      },
      message: 'Maximum discount amount is required for percentage discounts and must be greater than 0'
    }
  },
  startDate: {
    type: Date,
    default: Date.now
  },
  expiryDate: {
    type: Date,
    default: null,
    validate: {
      validator: function(value) {
        if (value === null) return true;
        return value > this.startDate;
      },
      message: 'Expiry date must be after start date'
    }
  },
  usageLimit: {
    type: Number,
    default: null,
    min: [1, 'Usage limit must be at least 1']
  },
  usedCount: {
    type: Number,
    default: 0,
    min: [0, 'Used count cannot be negative']
  },
  status: {
    type: String,
    enum: {
      values: ['active', 'inactive'],
      message: 'Status must be either "active" or "inactive"'
    },
    default: 'active'
  },
  createdAt: {
    type: Date,
    default: Date.now
  },
  updatedAt: {
    type: Date,
    default: Date.now
  }
}, {
  timestamps: true,
  toJSON: { virtuals: true },
  toObject: { virtuals: true }
});

// Indexes
couponSchema.index({ code: 1 }, { unique: true });
couponSchema.index({ status: 1 });
couponSchema.index({ expiryDate: 1 });
couponSchema.index({ startDate: 1 });

// Virtual for checking if coupon is expired
couponSchema.virtual('isExpired').get(function() {
  if (!this.expiryDate) return false;
  return new Date() > this.expiryDate;
});

// Virtual for checking if coupon is active
couponSchema.virtual('isActive').get(function() {
  if (this.status !== 'active') return false;
  if (this.isExpired) return false;
  if (this.usageLimit && this.usedCount >= this.usageLimit) return false;
  if (new Date() < this.startDate) return false;
  return true;
});

// Method to check if coupon is valid for a given order amount
couponSchema.methods.isValidForOrder = function(orderAmount) {
  if (!this.isActive) return false;
  if (orderAmount < this.minOrderAmount) return false;
  return true;
};

// Method to calculate discount amount for an order
couponSchema.methods.calculateDiscount = function(orderAmount) {
  if (!this.isValidForOrder(orderAmount)) {
    return 0;
  }

  let discountAmount = 0;
  
  if (this.discountType === 'percentage') {
    discountAmount = (orderAmount * this.discountValue) / 100;
    if (this.maxDiscountAmount && discountAmount > this.maxDiscountAmount) {
      discountAmount = this.maxDiscountAmount;
    }
  } else {
    discountAmount = this.discountValue;
  }

  // Ensure discount doesn't exceed order amount
  return Math.min(discountAmount, orderAmount);
};

// Pre-save hook to handle maxDiscountAmount for fixed discounts
couponSchema.pre('save', function(next) {
  if (this.discountType === 'fixed') {
    this.maxDiscountAmount = undefined;
  } else if (this.discountType === 'percentage' && !this.maxDiscountAmount) {
    this.invalidate('maxDiscountAmount', 'Maximum discount amount is required for percentage discounts');
  }
  next();
});

// Pre-validate hook to ensure maxDiscountAmount is set for percentage discounts
couponSchema.pre('validate', function(next) {
  if (this.discountType === 'percentage' && this.maxDiscountAmount === undefined) {
    this.invalidate('maxDiscountAmount', 'Maximum discount amount is required for percentage discounts');
  }
  next();
});

const Coupon = mongoose.model('Coupon', couponSchema);

module.exports = Coupon;