import express, { Request, Response } from 'express';
import { Op } from 'sequelize';
import Message from '../models/Message';
import ChatRoomMember from '../models/ChatRoomMember';

const router = express.Router();

type MarkReadBody = {
  roomId?: number | string;
  userId?: string;
  messageIds?: number[];
};

// Get messages for a room
router.get('/room/:roomId', async (req, res) => {
  try {
    const { roomId } = req.params;
    const { page = 1, limit = 50, userId } = req.query;

    const roomIdNum = parseInt(roomId);
    if (isNaN(roomIdNum)) {
      return res.status(400).json({
        success: false,
        message: 'Invalid room ID',
      });
    }

    const pageNum = parseInt(page as string);
    const limitNum = parseInt(limit as string);
    const offset = (pageNum - 1) * limitNum;

    // Verify user is a member of the room
    if (userId) {
      const membership = await ChatRoomMember.findOne({
        where: { room_id: roomIdNum, user_id: userId as string },
      });

      if (!membership) {
        return res.status(403).json({
          success: false,
          message: 'You are not a member of this room',
        });
      }
    }

    const { User } = require('../models');
    const { count, rows } = await Message.findAndCountAll({
      where: { room_id: roomIdNum },
      include: [
        {
          model: User,
          as: 'sender',
          attributes: ['user_id', 'name', 'avatar', 'role'],
        },
      ],
      order: [['createdAt', 'DESC']],
      limit: limitNum,
      offset,
    });

    return res.json({
      success: true,
      data: rows.reverse(), // Reverse to show oldest first
      pagination: {
        page: pageNum,
        limit: limitNum,
        total: count,
        totalPages: Math.ceil(count / limitNum),
      },
    });
  } catch (error: any) {
    console.error('Error fetching messages:', error);
    return res.status(500).json({ success: false, message: error.message });
  }
});

// Mark messages as read (POST + PATCH — บาง reverse proxy เช่น nginx บล็อก PATCH)
const markMessagesRead = async (req: Request, res: Response) => {
  try {
    const { roomId: roomIdRaw, userId, messageIds } = req.body as MarkReadBody;

    const roomId = Number(roomIdRaw);
    if (!roomIdRaw || Number.isNaN(roomId) || !userId) {
      return res.status(400).json({
        success: false,
        message: 'Room ID and User ID are required',
      });
    }

    // Verify user is a member of the room
    const membership = await ChatRoomMember.findOne({
      where: { room_id: roomId, user_id: userId },
    });

    if (!membership) {
      return res.status(403).json({
        success: false,
        message: 'You are not a member of this room',
      });
    }

    // Update messages
    const whereClause: any = {
      room_id: roomId,
      sender_id: { [Op.ne]: userId },
      is_read: false,
    };

    if (Array.isArray(messageIds) && messageIds.length > 0) {
      whereClause.id = { [Op.in]: messageIds };
    }

    // ดึง id ที่จะถูก mark ก่อน เพื่อ broadcast read_receipt ที่แม่นยำ
    const targets = await Message.findAll({
      where: whereClause,
      attributes: ['id', 'sender_id'],
      raw: true,
    });

    if (targets.length > 0) {
      await Message.update(
        { is_read: true },
        { where: { id: { [Op.in]: targets.map((t: any) => t.id) } } }
      );
    }

    // Broadcast read_receipt ให้ทุกคนในห้อง (รวมผู้ส่งเดิม)
    try {
      const io = req.app.locals.io;
      if (io && targets.length > 0) {
        io.to(`room:${roomId}`).emit('messages:read', {
          roomId,
          readBy: userId,
          messageIds: targets.map((t: any) => t.id),
        });
      }
    } catch (e) {
      console.warn('emit messages:read failed', e);
    }

    return res.json({
      success: true,
      message: 'Messages marked as read',
      count: targets.length,
    });
  } catch (error: any) {
    console.error('Error marking messages as read:', error);
    return res.status(500).json({ success: false, message: error.message });
  }
};

router.patch('/read', markMessagesRead);
router.post('/read', markMessagesRead);

// Get unread message count for a user
router.get('/unread/:userId', async (req, res) => {
  try {
    const { userId } = req.params;

    // Get all rooms user is a member of
    const memberships = await ChatRoomMember.findAll({
      where: { user_id: userId },
      attributes: ['room_id'],
    });

    const roomIds = memberships.map((m: any) => m.room_id);

    if (roomIds.length === 0) {
      return res.json({
        success: true,
        data: { total: 0, byRoom: {} },
      });
    }

    // Count unread messages per room
    const { fn, col } = require('sequelize');
    const unreadMessages = await Message.findAll({
      where: {
        room_id: { [Op.in]: roomIds },
        sender_id: { [Op.ne]: userId },
        is_read: false,
      },
      attributes: [
        'room_id',
        [fn('COUNT', col('id')), 'count'],
      ],
      group: ['room_id'],
      raw: true,
    });

    const byRoom: Record<string, number> = {};
    let total = 0;

    unreadMessages.forEach((msg: any) => {
      const count = parseInt(msg.count);
      byRoom[msg.room_id] = count;
      total += count;
    });

    return res.json({
      success: true,
      data: { total, byRoom },
    });
  } catch (error: any) {
    console.error('Error fetching unread count:', error);
    return res.status(500).json({ success: false, message: error.message });
  }
});

export default router;
