const BaseModel = require('./BaseModel');
const mongoose = require('mongoose');

const discountSchema = new mongoose.Schema({
  name: {
    type: String,
    required: [true, 'Discount name is required'],
    trim: true,
    maxlength: [100, 'Discount name cannot exceed 100 characters']
  },
  type: {
    type: String,
    enum: ['percentage', 'fixed'],
    required: [true, 'Discount type is required']
  },
  value: {
    type: Number,
    required: [true, 'Discount value is required'],
    min: [0, 'Discount value cannot be negative']
  },
  status: {
    type: Boolean,
    default: true
  }
}, {
  timestamps: true,
  toJSON: { virtuals: true },
  toObject: { virtuals: true }
});

// Indexes for better performance
discountSchema.index({ name: 1 });
discountSchema.index({ type: 1 });
discountSchema.index({ status: 1 });
discountSchema.index({ name: 'text' }); // Text search

// Virtual for getting items using this discount
discountSchema.virtual('items', {
  ref: 'Item',
  localField: '_id',
  foreignField: 'discountId'
});

class Discount extends BaseModel {
  static get schema() {
    return discountSchema;
  }

  /**
   * Initialize the Discount model
   */
  static init() {
    const model = super.init();
    
    // Drop old conflicting indexes
    if (model.collection) {
      // Drop old code index that's causing duplicate key errors
      model.collection.dropIndex('code_1').catch(() => {
        // Ignore error if index doesn't exist
      });
      
      // Create new text index
      setTimeout(() => {
        model.collection.createIndex({
          name: 'text'
        }).catch(err => {
          console.warn('Failed to create text index for Discount:', err.message);
        });
      }, 100); // Small delay to ensure drops complete
    }
    
    return model;
  }

  /**
   * Get all discounts with pagination and search
   */
  static async findAllActive(options = {}) {
    const { page = 1, limit = 10, search } = options;

    let query = { status: true };

    // Add search filter
    if (search) {
      query.$text = { $search: search };
    }

    return this.paginate(query, {
      page,
      limit,
      sort: search ? { score: { $meta: 'textScore' } } : { createdAt: -1 },
      select: 'name type value status createdAt updatedAt',
      lean: true
    });
  }

  /**
   * Get discount by ID with associated items count
   */
  static async findByIdWithDetails(id) {
    return this.aggregate([
      {
        $match: {
          _id: new mongoose.Types.ObjectId(id)
        }
      },
      {
        $lookup: {
          from: 'items',
          let: { discountId: '$_id' },
          pipeline: [
            {
              $match: {
                $expr: {
                  $and: [
                    { $eq: ['$discountId', '$$discountId'] },
                    { $eq: ['$status', true] }
                  ]
                }
              }
            },
            {
              $count: 'count'
            }
          ],
          as: 'itemStats'
        }
      },
      {
        $addFields: {
          itemCount: { $arrayElemAt: ['$itemStats.count', 0] },
          id: '$_id'
        }
      },
      {
        $project: {
          itemStats: 0,
          __v: 0
        }
      }
    ]).then(results => results[0] || null);
  }

  /**
   * Create new discount with validation
   */
  static async createDiscount(data) {
    const { name, type, value } = data;

    // Check if discount name already exists
    const existingDiscount = await this.findOne({
      name: new RegExp(`^${name.trim()}$`, 'i')
    });

    if (existingDiscount) {
      throw new Error('Discount name already exists');
    }

    // Validate percentage value
    if (type === 'percentage' && value > 100) {
      throw new Error('Percentage value cannot exceed 100%');
    }

    return this.create({
      name: name.trim(),
      type,
      value
    });
  }

  /**
   * Update discount with validation
   */
  static async updateDiscount(id, updateData) {
    const { name, type, value, status } = updateData;

    // Check if new discount name conflicts with existing discount
    if (name) {
      const existingDiscount = await this.findOne({
        name: new RegExp(`^${name.trim()}$`, 'i'),
        _id: { $ne: id }
      });

      if (existingDiscount) {
        throw new Error('Discount name already exists');
      }
    }

    // Validate percentage value
    if (type === 'percentage' && value > 100) {
      throw new Error('Percentage value cannot exceed 100%');
    }

    const updateFields = {};
    if (name !== undefined) updateFields.name = name.trim();
    if (type !== undefined) updateFields.type = type;
    if (value !== undefined) updateFields.value = value;
    if (status !== undefined) updateFields.status = status;

    return this.update(id, updateFields);
  }

  /**
   * Permanently delete discount (hard delete)
   */
  static async deleteDiscount(id) {
    const discount = await this.findById(id);
    if (!discount) {
      return null;
    }
    await discount.deleteOne();
    return discount;
  }

  /**
   * Get discount statistics
   */
  static async getStatistics() {
    return this.aggregate([
      {
        $group: {
          _id: null,
          totalDiscounts: { $sum: 1 },
          activeDiscounts: {
            $sum: {
              $cond: [{ $eq: ['$status', true] }, 1, 0]
            }
          },
          inactiveDiscounts: {
            $sum: {
              $cond: [{ $eq: ['$status', false] }, 1, 0]
            }
          },
          averageValue: { $avg: '$value' },
          maxValue: { $max: '$value' },
          minValue: { $min: '$value' }
        }
      }
    ]).then(results => results[0] || {
      totalDiscounts: 0,
      activeDiscounts: 0,
      inactiveDiscounts: 0,
      averageValue: 0,
      maxValue: 0,
      minValue: 0
    });
  }
}

module.exports = Discount;
