/**
 * Messaging Routes
 * API endpoints for conversations and messages
 */

const express = require('express');
const router = express.Router();
const { authenticateUser } = require('../middleware/auth');
const messagingService = require('../services/messagingService');
const db = require('../database/db');

/**
 * GET /api/conversations
 * Get all conversations for the current user
 */
router.get('/conversations', authenticateUser, async (req, res) => {
  try {
    const { limit, offset } = req.query;
    const conversations = await messagingService.getUserConversations(
      req.user.id,
      { 
        limit: limit ? parseInt(limit) : 50,
        offset: offset ? parseInt(offset) : 0
      }
    );
    
    res.json({
      success: true,
      conversations
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

/**
 * POST /api/conversations/direct
 * Get or create a direct conversation with another user
 */
router.post('/conversations/direct', authenticateUser, async (req, res) => {
  try {
    const { userId } = req.body;
    
    if (!userId) {
      return res.status(400).json({
        success: false,
        error: 'userId is required'
      });
    }
    
    const conversation = await messagingService.getOrCreateDirectConversation(
      req.user.id,
      userId
    );
    
    res.json({
      success: true,
      conversation
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

/**
 * POST /api/conversations/group
 * Create a new group conversation
 */
router.post('/conversations/group', authenticateUser, async (req, res) => {
  try {
    const { title, description, participantIds } = req.body;
    
    if (!title) {
      return res.status(400).json({
        success: false,
        error: 'title is required'
      });
    }
    
    const conversation = await messagingService.createGroupConversation(
      req.user.id,
      { title, description, participantIds }
    );
    
    res.json({
      success: true,
      conversation
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

/**
 * GET /api/conversations/:id
 * Get conversation details
 */
router.get('/conversations/:id', authenticateUser, async (req, res) => {
  try {
    const conversation = await messagingService.getConversation(
      req.params.id,
      req.user.id
    );
    
    res.json({
      success: true,
      conversation
    });
  } catch (error) {
    res.status(404).json({
      success: false,
      error: error.message
    });
  }
});

/**
 * GET /api/conversations/:id/messages
 * Get messages for a conversation
 */
router.get('/conversations/:id/messages', authenticateUser, async (req, res) => {
  try {
    const { limit, before } = req.query;
    
    const messages = await messagingService.getMessages(
      req.params.id,
      req.user.id,
      {
        limit: limit ? parseInt(limit) : 50,
        before: before
      }
    );
    
    res.json({
      success: true,
      messages
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

/**
 * POST /api/conversations/:id/messages
 * Send a message to a conversation
 */
router.post('/conversations/:id/messages', authenticateUser, async (req, res) => {
  try {
    const { content, contentType, metadata, replyToId, identityId } = req.body;
    
    if (!content) {
      return res.status(400).json({
        success: false,
        error: 'content is required'
      });
    }
    
    const message = await messagingService.sendMessage(
      req.user.id,
      req.params.id,
      { content, contentType, metadata, replyToId, identityId }
    );
    
    // Emit via Socket.io (will be handled by socket service)
    if (req.app.get('io')) {
      req.app.get('io').to(req.params.id).emit('new_message', message);
    }
    
    res.json({
      success: true,
      message
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

/**
 * PUT /api/messages/:id
 * Edit a message
 */
router.put('/messages/:id', authenticateUser, async (req, res) => {
  try {
    const { content } = req.body;
    
    if (!content) {
      return res.status(400).json({
        success: false,
        error: 'content is required'
      });
    }
    
    const message = await messagingService.editMessage(
      req.user.id,
      req.params.id,
      content
    );
    
    // Emit via Socket.io
    if (req.app.get('io')) {
      req.app.get('io').to(message.conversation_id).emit('message_edited', {
        messageId: message.id,
        content: message.content_encrypted,
        editedAt: message.edited_at
      });
    }
    
    res.json({
      success: true,
      message
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

/**
 * DELETE /api/messages/:id
 * Delete a message
 */
router.delete('/messages/:id', authenticateUser, async (req, res) => {
  try {
    await messagingService.deleteMessage(req.user.id, req.params.id);
    
    // Emit via Socket.io
    if (req.app.get('io')) {
      const msgResult = await db.query(
        'SELECT conversation_id FROM messages WHERE id = $1',
        [req.params.id]
      );
      if (msgResult.rows.length > 0) {
        req.app.get('io').to(msgResult.rows[0].conversation_id).emit('message_deleted', {
          messageId: req.params.id
        });
      }
    }
    
    res.json({
      success: true
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

/**
 * POST /api/messages/:id/reactions
 * Add reaction to a message
 */
router.post('/messages/:id/reactions', authenticateUser, async (req, res) => {
  try {
    const { emoji } = req.body;
    
    if (!emoji) {
      return res.status(400).json({
        success: false,
        error: 'emoji is required'
      });
    }
    
    await messagingService.addReaction(req.user.id, req.params.id, emoji);
    
    // Emit via Socket.io
    if (req.app.get('io')) {
      const msgResult = await db.query(
        'SELECT conversation_id FROM messages WHERE id = $1',
        [req.params.id]
      );
      if (msgResult.rows.length > 0) {
        req.app.get('io').to(msgResult.rows[0].conversation_id).emit('reaction_added', {
          messageId: req.params.id,
          userId: req.user.id,
          emoji
        });
      }
    }
    
    res.json({
      success: true
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

/**
 * DELETE /api/messages/:id/reactions/:emoji
 * Remove reaction from a message
 */
router.delete('/messages/:id/reactions/:emoji', authenticateUser, async (req, res) => {
  try {
    await messagingService.removeReaction(
      req.user.id,
      req.params.id,
      req.params.emoji
    );
    
    // Emit via Socket.io
    if (req.app.get('io')) {
      const msgResult = await db.query(
        'SELECT conversation_id FROM messages WHERE id = $1',
        [req.params.id]
      );
      if (msgResult.rows.length > 0) {
        req.app.get('io').to(msgResult.rows[0].conversation_id).emit('reaction_removed', {
          messageId: req.params.id,
          userId: req.user.id,
          emoji: req.params.emoji
        });
      }
    }
    
    res.json({
      success: true
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

/**
 * POST /api/conversations/:id/read
 * Mark conversation as read
 */
router.post('/conversations/:id/read', authenticateUser, async (req, res) => {
  try {
    await messagingService.markAsRead(req.user.id, req.params.id);
    
    res.json({
      success: true
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

/**
 * POST /api/conversations/:id/participants
 * Add participants to a group conversation
 */
router.post('/conversations/:id/participants', authenticateUser, async (req, res) => {
  try {
    const { participantIds } = req.body;
    
    if (!participantIds || !Array.isArray(participantIds)) {
      return res.status(400).json({
        success: false,
        error: 'participantIds array is required'
      });
    }
    
    await messagingService.addParticipants(
      req.user.id,
      req.params.id,
      participantIds
    );
    
    // Emit via Socket.io
    if (req.app.get('io')) {
      req.app.get('io').to(req.params.id).emit('participants_added', {
        conversationId: req.params.id,
        participantIds
      });
    }
    
    res.json({
      success: true
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

/**
 * DELETE /api/conversations/:id/participants/:userId
 * Remove participant from a group conversation
 */
router.delete('/conversations/:id/participants/:userId', authenticateUser, async (req, res) => {
  try {
    await messagingService.removeParticipant(
      req.user.id,
      req.params.id,
      req.params.userId
    );
    
    // Emit via Socket.io
    if (req.app.get('io')) {
      req.app.get('io').to(req.params.id).emit('participant_removed', {
        conversationId: req.params.id,
        userId: req.params.userId
      });
    }
    
    res.json({
      success: true
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

/**
 * GET /api/users/search
 * Search for users by domain/username
 */
router.get('/users/search', authenticateUser, async (req, res) => {
  try {
    const { q, limit } = req.query;
    
    if (!q) {
      return res.status(400).json({
        success: false,
        error: 'q (query) parameter is required'
      });
    }
    
    const users = await messagingService.searchUsers(
      q,
      req.user.id,
      limit ? parseInt(limit) : 10
    );
    
    res.json({
      success: true,
      users
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

module.exports = router;
