const Chat = require('../models/Chat');
const Message = require('../models/Message');
const { User } = require('../models/user');

/**
 * @desc    Ottieni tutte le chat dell'utente
 * @route   GET /api/trasporti/chats
 * @access  Private
 */
const getMyChats = async (req, res) => {
  try {
    const userId = req.user._id;
    const idapp = req.user.idapp;
    const { page = 1, limit = 20 } = req.query;

    if (!idapp) {
      return res.status(400).json({
        success: false,
        message: 'idapp è obbligatorio'
      });
    }

    const skip = (parseInt(page) - 1) * parseInt(limit);

    const chats = await Chat.find({
      idapp,
      participants: userId,
      isActive: true,
      blockedBy: { $ne: userId }
    })
      .populate('participants', 'username name surname profile.img')
      .populate('rideId', 'departure destination dateTime status')
      .sort({ updatedAt: -1 })
      .skip(skip)
      .limit(parseInt(limit));

    // Aggiungi conteggio non letti per ogni chat
    const chatsWithUnread = chats.map(chat => {
      const chatObj = chat.toObject();
      chatObj.unreadCount = chat.getUnreadForUser(userId);
      
      // Trova l'altro partecipante (per chat dirette)
      if (chat.type === 'direct') {
        chatObj.otherParticipant = chat.participants.find(
          p => p._id.toString() !== userId.toString()
        );
      }
      
      return chatObj;
    });

    const total = await Chat.countDocuments({
      idapp,
      participants: userId,
      isActive: true
    });

    res.json({
      success: true,
      data: chatsWithUnread,
      pagination: {
        page: parseInt(page),
        limit: parseInt(limit),
        total,
        pages: Math.ceil(total / parseInt(limit))
      }
    });

  } catch (error) {
    console.error('Errore recupero chat:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nel recupero delle chat',
      error: error.message
    });
  }
};

/**
 * @desc    Ottieni o crea una chat diretta con un utente
 * @route   POST /api/trasporti/chats/direct
 * @access  Private
 */
const getOrCreateDirectChat = async (req, res) => {
  try {
    const userId = req.user._id;
    const idapp = req.user.idapp;
    const { otherUserId, rideId } = req.body;

    if (!idapp || !otherUserId) {
      return res.status(400).json({
        success: false,
        message: 'idapp e otherUserId sono obbligatori'
      });
    }

    // Verifica che l'altro utente esista
    const otherUser = await User.findById(otherUserId);
    if (!otherUser) {
      return res.status(404).json({
        success: false,
        message: 'Utente non trovato'
      });
    }

    // Non puoi chattare con te stesso
    if (userId.toString() === otherUserId) {
      return res.status(400).json({
        success: false,
        message: 'Non puoi creare una chat con te stesso'
      });
    }

    const chat = await Chat.findOrCreateDirect(idapp, userId, otherUserId, rideId);

    await chat.populate('participants', 'username name surname profile.img');
    await chat.populate('rideId', 'departure destination dateTime');

    const chatObj = chat.toObject();
    chatObj.otherParticipant = chat.participants.find(
      p => p._id.toString() !== userId.toString()
    );
    chatObj.unreadCount = chat.getUnreadForUser(userId);

    res.json({
      success: true,
      data: chatObj
    });

  } catch (error) {
    console.error('Errore creazione chat:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nella creazione della chat',
      error: error.message
    });
  }
};

/**
 * @desc    Ottieni una chat per ID
 * @route   GET /api/trasporti/chats/:id
 * @access  Private
 */
const getChatById = async (req, res) => {
  try {
    const { id } = req.params;
    const userId = req.user._id;

    const chat = await Chat.findById(id)
      .populate('participants', 'username name surname profile.img profile.Cell')
      .populate('rideId', 'departure destination dateTime status type');

    if (!chat) {
      return res.status(404).json({
        success: false,
        message: 'Chat non trovata'
      });
    }

    // Verifica che l'utente sia partecipante
    if (!chat.hasParticipant(userId)) {
      return res.status(403).json({
        success: false,
        message: 'Non sei autorizzato ad accedere a questa chat'
      });
    }

    // Marca come letta
    await chat.markAsRead(userId);

    const chatObj = chat.toObject();
    chatObj.unreadCount = 0; // Appena marcata come letta
    
    if (chat.type === 'direct') {
      chatObj.otherParticipant = chat.participants.find(
        p => p._id.toString() !== userId.toString()
      );
    }

    res.json({
      success: true,
      data: chatObj
    });

  } catch (error) {
    console.error('Errore recupero chat:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nel recupero della chat',
      error: error.message
    });
  }
};

/**
 * @desc    Ottieni i messaggi di una chat
 * @route   GET /api/trasporti/chats/:id/messages
 * @access  Private
 */
const getChatMessages = async (req, res) => {
  try {
    const { id } = req.params;
    const idapp = req.user.idapp;
    const { before, after, limit = 50 } = req.query;
    const userId = req.user._id;

    // Verifica accesso alla chat
    const chat = await Chat.findById(id);
    if (!chat) {
      return res.status(404).json({
        success: false,
        message: 'Chat non trovata'
      });
    } 

    if (!chat.hasParticipant(userId)) {
      return res.status(403).json({
        success: false,
        message: 'Non sei autorizzato'
      });
    }

    const messages = await Message.getByChat(idapp, id, {
      limit: parseInt(limit),
      before,
      after
    });

    // Marca messaggi come letti
    await Promise.all(
      messages
        .filter(m => m.senderId && m.senderId._id.toString() !== userId.toString())
        .map(m => m.markAsReadBy(userId))
    );

    // Aggiorna unread count nella chat
    await chat.markAsRead(userId);

    res.json({
      success: true,
      data: messages.reverse(), // Ordine cronologico
      hasMore: messages.length === parseInt(limit)
    });

  } catch (error) {
    console.error('Errore recupero messaggi:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nel recupero dei messaggi',
      error: error.message
    });
  }
};

/**
 * @desc    Invia un messaggio
 * @route   POST /api/trasporti/chats/:id/messages
 * @access  Private
 */
const sendMessage = async (req, res) => {
  try {
    const { id } = req.params;
    const idapp = req.user.idapp;
    const { text, type = 'text', metadata, replyTo } = req.body;
    const userId = req.user._id;

    if (!idapp || !text) {
      return res.status(400).json({
        success: false,
        message: 'idapp e text sono obbligatori'
      });
    }

    // Verifica accesso alla chat
    const chat = await Chat.findById(id);
    if (!chat) {
      return res.status(404).json({
        success: false,
        message: 'Chat non trovata'
      });
    }

    if (!chat.hasParticipant(userId)) {
      return res.status(403).json({
        success: false,
        message: 'Non sei autorizzato'
      });
    }

    // Verifica che la chat non sia bloccata
    if (chat.isBlockedFor(userId)) {
      return res.status(403).json({
        success: false,
        message: 'Non puoi inviare messaggi in questa chat'
      });
    }

    // Crea il messaggio
    const message = new Message({
      idapp,
      chatId: id,
      senderId: userId,
      text,
      type,
      metadata: metadata || {},
      replyTo: replyTo || null,
      readBy: [{ userId, readAt: new Date() }] // Il mittente l'ha già letto
    });

    await message.save();

    // Popola per la risposta
    await message.populate('senderId', 'username name surname profile.img');
    if (replyTo) {
      await message.populate('replyTo', 'text senderId');
    }

    // TODO: Inviare notifica push agli altri partecipanti

    res.status(201).json({
      success: true,
      data: message
    });

  } catch (error) {
    console.error('Errore invio messaggio:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nell\'invio del messaggio',
      error: error.message
    });
  }
};

/**
 * @desc    Marca tutti i messaggi di una chat come letti
 * @route   PUT /api/trasporti/chats/:id/read
 * @access  Private
 */
const markChatAsRead = async (req, res) => {
  try {
    const { id } = req.params;
    const userId = req.user._id;

    const chat = await Chat.findById(id);
    if (!chat) {
      return res.status(404).json({
        success: false,
        message: 'Chat non trovata'
      });
    }

    if (!chat.hasParticipant(userId)) {
      return res.status(403).json({
        success: false,
        message: 'Non sei autorizzato'
      });
    }

    await chat.markAsRead(userId);

    // Marca tutti i messaggi come letti
    await Message.updateMany(
      {
        chatId: id,
        senderId: { $ne: userId },
        'readBy.userId': { $ne: userId }
      },
      {
        $push: { readBy: { userId, readAt: new Date() } }
      }
    );

    res.json({
      success: true,
      message: 'Chat marcata come letta'
    });

  } catch (error) {
    console.error('Errore marca come letto:', error);
    res.status(500).json({
      success: false,
      message: 'Errore',
      error: error.message
    });
  }
};

/**
 * @desc    Blocca/sblocca una chat
 * @route   PUT /api/trasporti/chats/:id/block
 * @access  Private
 */
const toggleBlockChat = async (req, res) => {
  try {
    const { id } = req.params;
    const { block } = req.body;
    const userId = req.user._id;

    const chat = await Chat.findById(id);
    if (!chat) {
      return res.status(404).json({
        success: false,
        message: 'Chat non trovata'
      });
    }

    if (!chat.hasParticipant(userId)) {
      return res.status(403).json({
        success: false,
        message: 'Non sei autorizzato'
      });
    }

    if (block) {
      if (!chat.blockedBy.includes(userId)) {
        chat.blockedBy.push(userId);
      }
    } else {
      chat.blockedBy = chat.blockedBy.filter(
        id => id.toString() !== userId.toString()
      );
    }

    await chat.save();

    res.json({
      success: true,
      message: block ? 'Chat bloccata' : 'Chat sbloccata',
      data: { blocked: block }
    });

  } catch (error) {
    console.error('Errore blocco chat:', error);
    res.status(500).json({
      success: false,
      message: 'Errore',
      error: error.message
    });
  }
};

/**
 * @desc    Muta/smuta notifiche di una chat
 * @route   PUT /api/trasporti/chats/:id/mute
 * @access  Private
 */
const toggleMuteChat = async (req, res) => {
  try {
    const { id } = req.params;
    const { mute } = req.body;
    const userId = req.user._id;

    const chat = await Chat.findById(id);
    if (!chat) {
      return res.status(404).json({
        success: false,
        message: 'Chat non trovata'
      });
    }

    if (!chat.hasParticipant(userId)) {
      return res.status(403).json({
        success: false,
        message: 'Non sei autorizzato'
      });
    }

    if (mute) {
      if (!chat.mutedBy.includes(userId)) {
        chat.mutedBy.push(userId);
      }
    } else {
      chat.mutedBy = chat.mutedBy.filter(
        id => id.toString() !== userId.toString()
      );
    }

    await chat.save();

    res.json({
      success: true,
      message: mute ? 'Notifiche disattivate' : 'Notifiche attivate',
      data: { muted: mute }
    });

  } catch (error) {
    console.error('Errore mute chat:', error);
    res.status(500).json({
      success: false,
      message: 'Errore',
      error: error.message
    });
  }
};

/**
 * @desc    Conta messaggi non letti totali
 * @route   GET /api/trasporti/chats/unread/count
 * @access  Private
 */
const getUnreadCount = async (req, res) => {
  try {
    const userId = req.user._id;
    const idapp = req.user.idapp;

    if (!idapp) {
      return res.status(400).json({
        success: false,
        message: 'idapp è obbligatorio'
      });
    }

    const chats = await Chat.find({
      idapp,
      participants: userId,
      isActive: true
    });

    let totalUnread = 0;
    const chatUnreads = [];

    for (const chat of chats) {
      const unread = chat.getUnreadForUser(userId);
      totalUnread += unread;
      if (unread > 0) {
        chatUnreads.push({
          chatId: chat._id,
          unread
        });
      }
    }

    res.json({
      success: true,
      data: {
        total: totalUnread,
        chats: chatUnreads
      }
    });

  } catch (error) {
    console.error('Errore conteggio non letti:', error);
    res.status(500).json({
      success: false,
      message: 'Errore',
      error: error.message
    });
  }
};

/**
 * @desc    Elimina un messaggio (soft delete)
 * @route   DELETE /api/trasporti/chats/:chatId/messages/:messageId
 * @access  Private
 */
const deleteMessage = async (req, res) => {
  try {
    const { chatId, messageId } = req.params;
    const userId = req.user._id;

    const message = await Message.findById(messageId);

    if (!message) {
      return res.status(404).json({
        success: false,
        message: 'Messaggio non trovato'
      });
    }

    if (message.chatId.toString() !== chatId) {
      return res.status(400).json({
        success: false,
        message: 'Messaggio non appartiene a questa chat'
      });
    }

    // Solo il mittente può eliminare
    if (message.senderId.toString() !== userId.toString()) {
      return res.status(403).json({
        success: false,
        message: 'Non sei autorizzato a eliminare questo messaggio'
      });
    }

    await message.softDelete();

    res.json({
      success: true,
      message: 'Messaggio eliminato'
    });

  } catch (error) {
    console.error('Errore eliminazione messaggio:', error);
    res.status(500).json({
      success: false,
      message: 'Errore',
      error: error.message
    });
  }
};

/**
 * @desc    Elimina una chat (soft delete)
 * @route   DELETE /api/trasporti/chats/:id
 * @access  Private
 */
const deleteChat = async (req, res) => {
  try {
    const { id } = req.params;
    const userId = req.user._id;

    const chat = await Chat.findById(id);

    if (!chat) {
      return res.status(404).json({
        success: false,
        message: 'Chat non trovata'
      });
    }

    // Verifica che l'utente sia partecipante
    if (!chat.hasParticipant(userId)) {
      return res.status(403).json({
        success: false,
        message: 'Non sei autorizzato a eliminare questa chat'
      });
    }

    // Soft delete: segna come non attiva per questo utente
    // Se vuoi hard delete, usa: await chat.deleteOne();
    
    // Opzione 1: Soft delete (chat rimane ma nascosta per questo utente)
    if (!chat.deletedBy) {
      chat.deletedBy = [];
    }
    
    if (!chat.deletedBy.includes(userId)) {
      chat.deletedBy.push(userId);
    }
    
    // Se tutti i partecipanti hanno eliminato, marca come non attiva
    if (chat.deletedBy.length === chat.participants.length) {
      chat.isActive = false;
    }
    
    await chat.save();

    res.json({
      success: true,
      message: 'Chat eliminata'
    });

  } catch (error) {
    console.error('Errore eliminazione chat:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nell\'eliminazione della chat',
      error: error.message
    });
  }
};

module.exports = {
  getMyChats,
  getOrCreateDirectChat,
  getChatById,
  getChatMessages,
  sendMessage,
  markChatAsRead,
  toggleBlockChat,
  toggleMuteChat,
  getUnreadCount,
  deleteMessage,
  deleteChat,
};