const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const MessageSchema = new Schema({
  idapp: {
    type: String,
    required: true,
    index: true
  },
  chatId: {
    type: Schema.Types.ObjectId,
    ref: 'Chat',
    required: true,
    index: true
  },
  senderId: {
    type: Schema.Types.ObjectId,
    ref: 'User',
    required: true
  },
  text: {
    type: String,
    trim: true,
    maxlength: 2000
  },
  type: {
    type: String,
    enum: ['text', 'ride_share', 'location', 'image', 'voice', 'system', 'ride_request', 'ride_accepted', 'ride_rejected'],
    default: 'text'
  },
  metadata: {
    // Per messaggi speciali (condivisione viaggio, posizione, ecc.)
    rideId: {
      type: Schema.Types.ObjectId,
      ref: 'Ride'
    },
    rideRequestId: {
      type: Schema.Types.ObjectId,
      ref: 'RideRequest'
    },
    location: {
      lat: Number,
      lng: Number,
      address: String
    },
    imageUrl: String,
    voiceUrl: String,
    voiceDuration: Number,
    systemAction: String
  },
  readBy: [{
    userId: {
      type: Schema.Types.ObjectId,
      ref: 'User'
    },
    readAt: {
      type: Date,
      default: Date.now
    }
  }],
  replyTo: {
    type: Schema.Types.ObjectId,
    ref: 'Message'
  },
  isEdited: {
    type: Boolean,
    default: false
  },
  editedAt: {
    type: Date
  },
  isDeleted: {
    type: Boolean,
    default: false
  },
  deletedAt: {
    type: Date
  },
  reactions: [{
    userId: {
      type: Schema.Types.ObjectId,
      ref: 'User'
    },
    emoji: String,
    createdAt: {
      type: Date,
      default: Date.now
    }
  }]
}, {
  timestamps: true,
  toJSON: { virtuals: true },
  toObject: { virtuals: true }
});

// Indici per query efficienti
MessageSchema.index({ chatId: 1, createdAt: -1 });
MessageSchema.index({ senderId: 1, createdAt: -1 });
MessageSchema.index({ idapp: 1, chatId: 1 });

// Virtual per verificare se il messaggio è stato letto da tutti
MessageSchema.virtual('isReadByAll').get(function() {
  // Logica da implementare confrontando con partecipanti chat
  return false;
});

// Metodo per marcare come letto da un utente
MessageSchema.methods.markAsReadBy = function(userId) {
  const alreadyRead = this.readBy.some(
    r => r.userId.toString() === userId.toString()
  );
  
  if (!alreadyRead) {
    this.readBy.push({
      userId,
      readAt: new Date()
    });
    return this.save();
  }
  return Promise.resolve(this);
};

// Metodo per verificare se è stato letto da un utente
MessageSchema.methods.isReadBy = function(userId) {
  return this.readBy.some(
    r => r.userId.toString() === userId.toString()
  );
};

// Metodo per aggiungere reazione
MessageSchema.methods.addReaction = function(userId, emoji) {
  // Rimuovi eventuale reazione precedente dello stesso utente
  this.reactions = this.reactions.filter(
    r => r.userId.toString() !== userId.toString()
  );
  
  this.reactions.push({
    userId,
    emoji,
    createdAt: new Date()
  });
  
  return this.save();
};

// Metodo per rimuovere reazione
MessageSchema.methods.removeReaction = function(userId) {
  this.reactions = this.reactions.filter(
    r => r.userId.toString() !== userId.toString()
  );
  return this.save();
};

// Metodo per soft delete
MessageSchema.methods.softDelete = function() {
  this.isDeleted = true;
  this.deletedAt = new Date();
  this.text = '[Messaggio eliminato]';
  return this.save();
};

// Metodo per modificare testo
MessageSchema.methods.editText = function(newText) {
  this.text = newText;
  this.isEdited = true;
  this.editedAt = new Date();
  return this.save();
};

// Metodo statico per ottenere messaggi di una chat con paginazione
// Message.js (model)

MessageSchema.statics.getByChat = async function(idapp, chatId, options = {}) {
  const { limit = 50, before, after } = options;
  
  const query = {
    idapp,
    chatId,
    isDeleted: false
  };

  // Filtra per timestamp
  if (before) {
    query.createdAt = { $lt: new Date(before) };
  }
  if (after) {
    query.createdAt = { $gt: new Date(after) };
  }

  // ✅ Sempre in ordine decrescente (dal più recente al più vecchio)
  return this.find(query)
    .populate('senderId', 'username name surname profile.img')
    .populate('replyTo', 'text senderId')
    .sort({ createdAt: -1 })  // -1 = più recente prima
    .limit(limit)
};

// Metodo statico per creare messaggio di sistema
MessageSchema.statics.createSystemMessage = async function(idapp, chatId, text, action = null) {
  const message = new this({
    idapp,
    chatId,
    senderId: null, // Sistema
    text,
    type: 'system',
    metadata: {
      systemAction: action
    }
  });
  return message.save();
};

// Metodo statico per contare messaggi non letti
MessageSchema.statics.countUnreadForUser = async function(idapp, chatId, userId) {
  return this.countDocuments({
    idapp,
    chatId,
    isDeleted: false,
    senderId: { $ne: userId },
    'readBy.userId': { $ne: userId }
  });
};

// Hook post-save per aggiornare la chat
MessageSchema.post('save', async function(doc) {
  try {
    const Chat = mongoose.model('Chat');
    const chat = await Chat.findById(doc.chatId);
    
    if (chat) {
      await chat.updateLastMessage(doc);
      await chat.incrementUnread(doc.senderId);
    }
  } catch (error) {
    console.error('Errore aggiornamento chat dopo messaggio:', error);
  }
});

const Message = mongoose.model('Message', MessageSchema);

module.exports = Message;