import { Router } from 'express';
import { prisma } from '../config/database.js';
import { authenticate } from '../middleware/auth.js';
import { AppError } from '../middleware/errorHandler.js';
import { getBlockedUserIds } from '../utils/blocked.js';

const router = Router();

router.get('/conversations', authenticate, async (req, res, next) => {
  try {
    // Exclude blocked users
    const blockedIds = await getBlockedUserIds(req.userId!);

    const conversations = await prisma.conversation.findMany({
      where: {
        OR: [{ user1Id: req.userId }, { user2Id: req.userId }],
        ...(blockedIds.length > 0 ? {
          AND: [
            { user1Id: { notIn: blockedIds } },
            { user2Id: { notIn: blockedIds } },
          ],
        } : {}),
      },
      include: {
        user1: { select: { id: true, fullName: true, nickname: true, avatar: true } },
        user2: { select: { id: true, fullName: true, nickname: true, avatar: true } },
        listing: { select: { id: true, title: true, price: true, images: { take: 1 } } },
        messages: { orderBy: { createdAt: 'desc' }, take: 1 },
      },
      orderBy: { updatedAt: 'desc' },
    });

    const result = await Promise.all(conversations.map(async (conv) => {
      const unreadCount = await prisma.message.count({
        where: { conversationId: conv.id, senderId: { not: req.userId }, isRead: false },
      });
      return {
        ...conv,
        lastMessage: conv.messages[0] || null,
        unreadCount,
      };
    }));

    res.json(result);
  } catch (error) {
    next(error);
  }
});

router.get('/conversations/:id/messages', authenticate, async (req, res, next) => {
  try {
    const conv = await prisma.conversation.findUnique({ where: { id: req.params.id } });
    if (!conv) throw new AppError(404, 'Conversation not found');
    if (conv.user1Id !== req.userId && conv.user2Id !== req.userId) throw new AppError(403, 'Not authorized');

    const { page = '1', pageSize = '50' } = req.query;
    const take = parseInt(pageSize as string);
    const skip = (parseInt(page as string) - 1) * take;

    const [messages, total] = await Promise.all([
      prisma.message.findMany({
        where: { conversationId: req.params.id },
        include: { sender: { select: { id: true, fullName: true, avatar: true } } },
        orderBy: { createdAt: 'asc' },
        skip,
        take,
      }),
      prisma.message.count({ where: { conversationId: req.params.id } }),
    ]);

    await prisma.message.updateMany({
      where: { conversationId: req.params.id, senderId: { not: req.userId }, isRead: false },
      data: { isRead: true },
    });

    res.json({
      data: messages,
      total,
      page: parseInt(page as string),
      pageSize: take,
      totalPages: Math.ceil(total / take),
    });
  } catch (error) {
    next(error);
  }
});

router.post('/conversations', authenticate, async (req, res, next) => {
  try {
    const { recipientId, listingId, message } = req.body;
    if (!recipientId) throw new AppError(400, 'Recipient ID is required');
    if (recipientId === req.userId) throw new AppError(400, 'Cannot message yourself');

    // Check blocked users
    const blockedIds = await getBlockedUserIds(req.userId!);
    if (blockedIds.includes(recipientId)) {
      throw new AppError(403, 'Cannot message this user');
    }

    const [id1, id2] = [req.userId!, recipientId].sort();
    const listingIdValue = listingId || undefined;

    let conversation = await prisma.conversation.findFirst({
      where: {
        user1Id: id1,
        user2Id: id2,
        ...(listingIdValue ? { listingId: listingIdValue } : { listingId: null }),
      },
    });

    if (!conversation) {
      conversation = await prisma.conversation.create({
        data: {
          user1Id: id1,
          user2Id: id2,
          ...(listingIdValue ? { listingId: listingIdValue } : {}),
        },
      });
    }

    if (message) {
      const msg = await prisma.message.create({
        data: { content: message, senderId: req.userId!, conversationId: conversation.id },
      });
      await prisma.conversation.update({ where: { id: conversation.id }, data: { updatedAt: new Date() } });

      // Send notification
      const sender = await prisma.user.findUnique({ where: { id: req.userId }, select: { fullName: true } });
      const notification = await prisma.notification.create({
        data: {
          userId: recipientId,
          type: 'NEW_MESSAGE',
          title: 'New Message',
          body: `${sender?.fullName || 'Someone'} sent you a message`,
          data: { conversationId: conversation.id },
        },
      });

      const io = req.app.get('io');
      if (io) {
        io.to(`user:${recipientId}`).emit('new_notification', notification);
      }
    }

    res.json(conversation);
  } catch (error) {
    next(error);
  }
});

router.delete('/conversations/:id', authenticate, async (req, res, next) => {
  try {
    const conv = await prisma.conversation.findUnique({ where: { id: req.params.id } });
    if (!conv) throw new AppError(404, 'Conversation not found');
    if (conv.user1Id !== req.userId && conv.user2Id !== req.userId) throw new AppError(403, 'Not authorized');

    await prisma.message.deleteMany({ where: { conversationId: req.params.id } });
    await prisma.conversation.delete({ where: { id: req.params.id } });

    res.json({ message: 'Conversation deleted' });
  } catch (error) {
    next(error);
  }
});

export default router;
