const mongoose = require('mongoose');

const prescriptionSchema = new mongoose.Schema({
  userId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User',
    required: true
  },
  orderId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Order',
    required: false,
    validate: {
      validator: function(v) {
        // Allow null/undefined or valid ObjectId
        if (v === null || v === undefined) return true;
        return mongoose.Types.ObjectId.isValid(v);
      },
      message: props => `${props.value} is not a valid order ID!`
    }
  },
  storeId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Store',
    required: true,
    index: true
  },
  images: [{
    path: { type: String, required: true },
    original_name: { type: String, required: true },
    mimetype: { type: String, required: true },
    size: { type: Number, required: true },
    is_primary: { type: Boolean, default: true },
    uploaded_at: { type: Date, default: Date.now }
  }],
  doctor_name: { type: String },
  patient_name: { type: String },
  patient_age: { type: Number },
  patient_gender: { type: String, enum: ['male', 'female', 'other'] },
  prescription_date: { type: Date, default: Date.now },
  status: {
    type: String,
    enum: ['pending', 'approved', 'rejected'],
    default: 'pending'
  },
  is_verified: { type: Boolean, default: false },
  verification_method: { type: String, enum: ['auto', 'manual'], default: 'manual' },
  verification_history: [{
    status: { type: String, required: true },
    changedAt: { type: Date, default: Date.now },
    comment: String,
    changedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
  }],
  reviewedBy: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User'
  },
  reviewedAt: {
    type: Date
  },
  rejectionReason: {
    type: String
  }
}, { 
  timestamps: true,
  toJSON: { virtuals: true },
  toObject: { virtuals: true }
});

// Add text index for search
prescriptionSchema.index({
  status: 'text'
});

// Add static methods to the schema
prescriptionSchema.statics.createPrescription = async function(data) {
  // If orderId is provided, ensure storeId is set from the order
  if (data.orderId) {
    const Order = mongoose.model('Order');
    const order = await Order.findById(data.orderId).select('store');
    if (order && order.store) {
      data.storeId = order.store;
    }
  }
  
  if (!data.storeId) {
    throw new Error('storeId is required for prescription');
  }
  
  return this.create(data);
};

prescriptionSchema.statics.updateStatus = async function(id, { status, reviewedBy, rejectionReason }) {
  // Validate status
  if (!['pending', 'approved', 'rejected'].includes(status)) {
    throw new Error('Invalid status. Must be one of: pending, approved, rejected');
  }

  // First update the prescription
  const updateData = {
    status,
    reviewedBy,
    reviewedAt: new Date(),
    ...(rejectionReason && { rejectionReason })
  };

  const updatedPrescription = await this.findByIdAndUpdate(
    id, 
    { 
      $set: updateData,
      $push: {
        verification_history: {
          status,
          changedBy: reviewedBy,
          comment: `Status changed to ${status}` + (rejectionReason ? ` - ${rejectionReason}` : ''),
          changedAt: new Date()
        }
      }
    }, 
    { new: true }
  );

  if (!updatedPrescription) {
    throw new Error('Prescription not found');
  }

  // If we have an orderId, update the order's status as well
  if (updatedPrescription.orderId) {
    const Order = require('./Order');
    const order = await Order.findById(updatedPrescription.orderId);
    
    if (order) {
      // Update order status based on prescription status
      let orderStatus = order.status;
      
      if (status === 'approved') {
        orderStatus = 'approved';
      } else if (status === 'rejected') {
        orderStatus = 'rejected';
        order.rejectionReason = rejectionReason || 'Prescription rejected';
      }
      
      // Update order's prescription status and main status
      order.prescriptionStatus = status;
      
      // Only update order status if it's not already in a terminal state
      const terminalStatuses = ['cancelled', 'delivered', 'refunded'];
      if (!terminalStatuses.includes(order.status)) {
        order.status = orderStatus;
      }
      
      // Add to status history
      order.statusHistory = order.statusHistory || [];
      order.statusHistory.push({
        status: order.status,
        changedAt: new Date(),
        changedBy: reviewedBy,
        comment: `Prescription ${status}` + (rejectionReason ? ` - ${rejectionReason}` : '')
      });
      
      await order.save();
    }
  }

  return updatedPrescription;
};

// Add instance and static methods
prescriptionSchema.statics.findByUserId = async function(userId, options = {}) {
  const { page = 1, limit = 10, sort = { uploadedAt: -1 } } = options;
  const skip = (page - 1) * limit;

  const [prescriptions, total] = await Promise.all([
    this.find({ userId })
      .sort(sort)
      .skip(skip)
      .limit(limit)
      .populate('orderId')
      .populate('reviewedBy', 'name email')
      .lean(),
    this.countDocuments({ userId })
  ]);

  return {
    prescriptions,
    total,
    page,
    totalPages: Math.ceil(total / limit)
  };
};

prescriptionSchema.statics.getPrescriptionDetails = function(prescriptionId) {
  return this.findById(prescriptionId)
    .populate('userId', 'name email phone')
    .populate('orderId')
    .populate('reviewedBy', 'name email');
};

// Get prescriptions by status with pagination and population
prescriptionSchema.statics.getByStatus = async function(status, { page = 1, limit = 10 }) {
  try {
    const query = { status };
    
    // Count total matching documents
    const total = await this.countDocuments(query);
    
    // Calculate pagination values
    const totalPages = Math.ceil(total / limit);
    const skip = (page - 1) * limit;
    
    // Execute query with pagination and population
    const prescriptions = await this.find(query)
      .populate({
        path: 'userId',
        select: 'name email phone'
      })
      .populate({
        path: 'orderId',
        select: 'orderNumber items totalAmount paymentStatus'
      })
      .populate({
        path: 'storeId',
        select: 'name address city state postalCode'
      })
      .sort({ createdAt: -1 })
      .skip(skip)
      .limit(parseInt(limit));
    
    return {
      prescriptions,
      total,
      page: parseInt(page),
      totalPages,
      limit: parseInt(limit)
    };
  } catch (error) {
    console.error('Error in getByStatus:', error);
    throw error;
  }
};

// Create and export the model
const Prescription = mongoose.model('Prescription', prescriptionSchema);
module.exports = Prescription;
