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

const addressSchema = new mongoose.Schema({
  user: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User',
    required: true
  },
  name: {
    type: String,
    required: [true, 'Please enter a name for this address'],
    trim: true,
    maxlength: [100, 'Name cannot exceed 100 characters']
  },
  contactNumber: {
    type: String,
    trim: true,
    default: ''
  },
  country: {
    type: String,
    default: 'India',
    trim: true
  },
  state: {
    type: String,
    required: [true, 'Please enter a state'],
    trim: true
  },
  city: {
    type: String,
    required: [true, 'Please enter a city'],
    trim: true
  },
  postcode: {
    type: String,
    trim: true,
    default: ''
  },
  address: {
    type: String,
    required: [true, 'Please enter an address'],
    trim: true
  },
  landmark: {
    type: String,
    trim: true
  },
  location: {
    type: {
      type: String,
      enum: ['Point'],
      default: 'Point'
    },
    coordinates: {
      type: [Number],
      validate: {
        validator: function(v) {
          return v.length === 2 && 
                 typeof v[0] === 'number' && 
                 typeof v[1] === 'number';
        },
        message: 'Location must be an array of [longitude, latitude]'
      }
    }
  },
  isDefault: {
    type: Boolean,
    default: false
  },
  type: {
    type: String,
    enum: ['home', 'work', 'other'],
    default: 'home'
  },
  status: {
    type: Boolean,
    default: true
  },
  deletedAt: Date
}, {
  timestamps: true,
  toJSON: { virtuals: true },
  toObject: { virtuals: true }
});

// Create a 2dsphere index for geospatial queries
addressSchema.index({ location: '2dsphere' });

class Address extends BaseModel {
  static get schema() {
    return addressSchema;
  }

  static async setDefaultAddress(userId, addressId) {
    // Remove default status from all other addresses
    await this.model.updateMany(
      { user: userId, _id: { $ne: addressId } },
      { $set: { isDefault: false } }
    );

    // Set the specified address as default
    return this.model.findByIdAndUpdate(
      addressId,
      { $set: { isDefault: true } },
      { new: true }
    );
  }

  static async getUserAddresses(userId) {
    return this.find(
      { user: userId, status: true },
      { sort: { isDefault: -1, createdAt: -1 } }
    );
  }

  // New method to create or update address for a user
  static async createOrUpdateAddress(userId, addressData) {
    // Check if an address with the same postcode and address already exists
    const existingAddress = await this.model.findOne({
      user: userId,
      postcode: addressData.postcode,
      address: addressData.address
    });

    if (existingAddress) {
      // Update existing address
      return this.model.findByIdAndUpdate(
        existingAddress._id,
        { 
          $set: {
            ...addressData,
            user: userId,
            updatedAt: new Date()
          }
        },
        { new: true }
      );
    } else {
      // Create new address
      return this.model.create({
        ...addressData,
        user: userId
      });
    }
  }
}

// Create the model using the schema
Address._model = mongoose.model('Address', addressSchema);

module.exports = Address;
