import express from 'express';
import { Op } from 'sequelize';
import ChatRoom from '../models/ChatRoom';
import ChatRoomMember from '../models/ChatRoomMember';
import User from '../models/User';
import { debugLog } from '../utils/logger';
import {
  invalidateUserRoomsCache,
  invalidateUsersFilterCache,
  roomsCache,
  usersFilterCache,
} from '../utils/chatCache';

const router = express.Router();

// Sync user (create or update user)
router.post('/users/sync', async (req, res) => {
  try {
    debugLog('📥 POST /api/chat/users/sync - Request received');
    debugLog('📦 Request body:', req.body);
    
    const { userId, name, email, role, avatar, status } = req.body;

    if (!userId || !name) {
      debugLog('❌ Missing userId or name');
      return res.status(400).json({
        success: false,
        message: 'User ID and name are required',
      });
    }

    // Find or create user
    let [user, created] = await User.findOrCreate({
      where: { user_id: userId },
      defaults: {
        user_id: userId,
        name,
        email: email || null,
        role: role || 'student',
        avatar: avatar || null,
        status: status || 'active',
      },
    });

    // Update user if it already exists
    if (!created) {
      debugLog(`🔄 Updating existing user: ${userId}`);
      await user.update({
        name,
        email: email || user.email,
        role: role || user.role,
        avatar: avatar || user.avatar,
        status: status || user.status,
      });
    } else {
      debugLog(`✨ Created new user: ${userId}`);
    }

    const responseData = {
      success: true,
      data: {
        user_id: user.user_id,
        name: user.name,
        email: user.email,
        role: user.role,
        avatar: user.avatar,
        status: user.status,
      },
    };

    debugLog('✅ User sync successful:', responseData);
    invalidateUsersFilterCache();
    invalidateUserRoomsCache(String(userId));
    return res.json(responseData);
  } catch (error: any) {
    console.error('❌ Error syncing user:', error);
    return res.status(500).json({ success: false, message: error.message });
  }
});

// Update user status
router.patch('/users/:userId/status', async (req, res) => {
  try {
    const { userId } = req.params;
    const { status } = req.body;

    const user = await User.findOne({ where: { user_id: userId } });

    if (!user) {
      return res.status(404).json({
        success: false,
        message: 'User not found',
      });
    }

    await user.update({ status });

    return res.json({
      success: true,
      data: {
        user_id: user.user_id,
        status: user.status,
      },
    });
  } catch (error: any) {
    console.error('Error updating user status:', error);
    return res.status(500).json({ success: false, message: error.message });
  }
});

// Get all rooms for a user
router.get('/rooms/:userId', async (req, res) => {
  try {
    debugLog('📥 GET /api/chat/rooms/:userId - Request received');
    debugLog('📦 Request params:', req.params);
    debugLog('📦 Request query:', req.query);
    
    const { userId } = req.params;

    const cacheKey = `rooms:${userId}`;
    if (roomsCache.isFresh(cacheKey)) {
      debugLog(`✅ Cache hit rooms for user ${userId}`);
      return res.json({ success: true, data: roomsCache.get(cacheKey) });
    }

    const staleRooms = roomsCache.getStale(cacheKey);
    if (staleRooms) {
      debugLog(`⚡ Stale cache rooms for user ${userId} — refresh in background`);
      (async () => {
        try {
          const memberships = await ChatRoomMember.findAll({
            where: { user_id: userId },
            include: [
              {
                model: ChatRoom,
                as: 'room',
                include: [
                  {
                    model: ChatRoomMember,
                    as: 'members',
                    include: [
                      {
                        model: User,
                        as: 'user',
                        attributes: ['user_id', 'name', 'avatar', 'role'],
                      },
                    ],
                  },
                ],
              },
            ],
            order: [['createdAt', 'DESC']],
          });
          const rooms = memberships.map((membership: any) => ({
            id: membership.room.id,
            name: membership.room.name,
            description: membership.room.description,
            type: membership.room.type,
            created_by: membership.room.created_by,
            role: membership.role,
            members: membership.room.members.map((m: any) => ({
              user_id: m.user.user_id,
              name: m.user.name,
              avatar: m.user.avatar,
              role: m.user.role,
              member_role: m.role,
            })),
            createdAt: membership.room.createdAt,
            updatedAt: membership.room.updatedAt,
          }));
          roomsCache.set(cacheKey, rooms);
        } catch (err) {
          console.error('❌ Background rooms refresh failed:', err);
        }
      })();
      return res.json({ success: true, data: staleRooms });
    }

    const memberships = await ChatRoomMember.findAll({
      where: { user_id: userId },
      include: [
        {
          model: ChatRoom,
          as: 'room',
          include: [
            {
              model: ChatRoomMember,
              as: 'members',
              include: [
                {
                  model: User,
                  as: 'user',
                  attributes: ['user_id', 'name', 'avatar', 'role'],
                },
              ],
            },
          ],
        },
      ],
      order: [['createdAt', 'DESC']],
    });

    const rooms = memberships.map((membership: any) => ({
      id: membership.room.id,
      name: membership.room.name,
      description: membership.room.description,
      type: membership.room.type,
      created_by: membership.room.created_by,
      role: membership.role,
      members: membership.room.members.map((m: any) => ({
        user_id: m.user.user_id,
        name: m.user.name,
        avatar: m.user.avatar,
        role: m.user.role,
        member_role: m.role,
      })),
      createdAt: membership.room.createdAt,
      updatedAt: membership.room.updatedAt,
    }));

    debugLog(`✅ Found ${rooms.length} rooms for user ${userId}`);
    roomsCache.set(cacheKey, rooms);
    return res.json({ success: true, data: rooms });
  } catch (error: any) {
    console.error('❌ Error fetching rooms:', error);
    return res.status(500).json({ success: false, message: error.message });
  }
});

// Create a new chat room
router.post('/rooms', async (req, res) => {
  try {
    const { name, description, type, created_by, members } = req.body;

    if (!name || !created_by) {
      return res.status(400).json({
        success: false,
        message: 'Room name and creator are required',
      });
    }

    // Create room
    const room = await ChatRoom.create({
      name,
      description,
      type: type || 'group',
      created_by,
    });

    // Add creator as admin
    await ChatRoomMember.create({
      room_id: room.id,
      user_id: created_by,
      role: 'admin',
    });

    // Add other members
    if (members && Array.isArray(members)) {
      for (const userId of members) {
        if (userId !== created_by) {
          await ChatRoomMember.create({
            room_id: room.id,
            user_id: userId,
            role: 'member',
          });
        }
      }
    }

    // Fetch room with members
    const roomWithMembers = await ChatRoom.findByPk(room.id, {
      include: [
        {
          model: ChatRoomMember,
          as: 'members',
          include: [
            {
              model: User,
              as: 'user',
              attributes: ['user_id', 'name', 'avatar', 'role'],
            },
          ],
        },
      ],
    });

    invalidateUserRoomsCache(String(created_by));
    if (members && Array.isArray(members)) {
      for (const memberId of members) {
        invalidateUserRoomsCache(String(memberId));
      }
    }

    return res.status(201).json({
      success: true,
      data: roomWithMembers,
    });
  } catch (error: any) {
    console.error('Error creating room:', error);
    return res.status(500).json({ success: false, message: error.message });
  }
});

// Get room details
router.get('/rooms/:roomId/details', async (req, res) => {
  try {
    const { roomId } = req.params;
    const roomIdNum = parseInt(roomId);

    if (isNaN(roomIdNum)) {
      return res.status(400).json({
        success: false,
        message: 'Invalid room ID',
      });
    }

    const room = await ChatRoom.findByPk(roomIdNum, {
      include: [
        {
          model: ChatRoomMember,
          as: 'members',
          include: [
            {
              model: User,
              as: 'user',
              attributes: ['user_id', 'name', 'avatar', 'role'],
            },
          ],
        },
      ],
    });

    if (!room) {
      return res.status(404).json({
        success: false,
        message: 'Room not found',
      });
    }

    return res.json({ success: true, data: room });
  } catch (error: any) {
    console.error('Error fetching room details:', error);
    return res.status(500).json({ success: false, message: error.message });
  }
});

// Add member to room
router.post('/rooms/:roomId/members', async (req, res) => {
  try {
    const { roomId } = req.params;
    const { userId, role = 'member' } = req.body;
    const roomIdNum = parseInt(roomId);

    if (isNaN(roomIdNum)) {
      return res.status(400).json({
        success: false,
        message: 'Invalid room ID',
      });
    }

    // Check if room exists
    const room = await ChatRoom.findByPk(roomIdNum);
    if (!room) {
      return res.status(404).json({
        success: false,
        message: 'Room not found',
      });
    }

    // Check if user is already a member
    const existingMember = await ChatRoomMember.findOne({
      where: { room_id: roomIdNum, user_id: userId },
    });

    if (existingMember) {
      return res.status(400).json({
        success: false,
        message: 'User is already a member of this room',
      });
    }

    // Add member
    const member = await ChatRoomMember.create({
      room_id: parseInt(roomId),
      user_id: userId,
      role,
    });

    const memberWithUser = await ChatRoomMember.findByPk(member.id, {
      include: [
        {
          model: User,
          as: 'user',
          attributes: ['user_id', 'name', 'avatar', 'role'],
        },
      ],
    });

    invalidateUserRoomsCache(String(userId));

    return res.status(201).json({
      success: true,
      data: memberWithUser,
    });
  } catch (error: any) {
    console.error('Error adding member:', error);
    return res.status(500).json({ success: false, message: error.message });
  }
});

// Remove member from room
router.delete('/rooms/:roomId/members/:userId', async (req, res) => {
  try {
    const { roomId, userId } = req.params;
    const roomIdNum = parseInt(roomId);

    if (isNaN(roomIdNum)) {
      return res.status(400).json({
        success: false,
        message: 'Invalid room ID',
      });
    }

    const member = await ChatRoomMember.findOne({
      where: { room_id: roomIdNum, user_id: userId },
    });

    if (!member) {
      return res.status(404).json({
        success: false,
        message: 'Member not found',
      });
    }

    await member.destroy();

    invalidateUserRoomsCache(String(userId));

    return res.json({
      success: true,
      message: 'Member removed from room',
    });
  } catch (error: any) {
    console.error('Error removing member:', error);
    return res.status(500).json({ success: false, message: error.message });
  }
});

// Find or create a direct message room between two users
router.post('/rooms/direct', async (req, res) => {
  try {
    debugLog('📥 POST /api/chat/rooms/direct - Request received');
    debugLog('📦 Request body:', req.body);

    const { userId1, userId2 } = req.body;

    if (!userId1 || !userId2) {
      debugLog('❌ Missing userId1 or userId2');
      return res.status(400).json({
        success: false,
        message: 'Both user IDs are required',
      });
    }

    // Check if both users exist (using user_id, not id)
    const user1 = await User.findOne({ where: { user_id: userId1 } });
    const user2 = await User.findOne({ where: { user_id: userId2 } });

    if (!user1 || !user2) {
      debugLog('❌ One or both users not found');
      return res.status(404).json({
        success: false,
        message: 'One or both users not found',
      });
    }

    // Check if a direct message room already exists between these two users
    const existingRooms = await ChatRoom.findAll({
      where: {
        type: 'direct',
      },
      include: [
        {
          model: ChatRoomMember,
          as: 'members',
          where: {
            user_id: [userId1, userId2],
          },
        },
      ],
    });

    // Filter to find rooms that have exactly these two users
    let directRoom = null;
    for (const room of existingRooms) {
      const members = await ChatRoomMember.findAll({
        where: { room_id: room.id },
      });
      if (
        members.length === 2 &&
        members.some((m) => m.user_id === userId1) &&
        members.some((m) => m.user_id === userId2)
      ) {
        directRoom = room;
        break;
      }
    }

    // If room exists, return it
    if (directRoom) {
      debugLog(`✅ Found existing direct room: ${directRoom.id}`);
      const roomWithMembers = await ChatRoom.findByPk(directRoom.id, {
        include: [
          {
            model: ChatRoomMember,
            as: 'members',
            include: [
              {
                model: User,
                as: 'user',
                attributes: ['user_id', 'name', 'avatar', 'role'],
              },
            ],
          },
          {
            model: User,
            as: 'creator',
            attributes: ['user_id', 'name', 'avatar', 'role'],
          },
        ],
      });

      return res.json({
        success: true,
        data: roomWithMembers,
        isNew: false,
      });
    }

    // Create new direct message room
    const roomName = `DM: ${user1.name} & ${user2.name}`;
    const newRoom = await ChatRoom.create({
      name: roomName,
      description: `Direct message between ${user1.name} and ${user2.name}`,
      type: 'direct',
      created_by: userId1,
    });
    debugLog(`✨ Created new direct room: ${newRoom.id}`);

    // Add both users as members
    await ChatRoomMember.create({
      room_id: newRoom.id,
      user_id: userId1,
      role: 'member',
    });
    await ChatRoomMember.create({
      room_id: newRoom.id,
      user_id: userId2,
      role: 'member',
    });
    debugLog(`➕ Added both users to room ${newRoom.id}`);

    // Fetch room with members
    const roomWithMembers = await ChatRoom.findByPk(newRoom.id, {
      include: [
        {
          model: ChatRoomMember,
          as: 'members',
          include: [
            {
              model: User,
              as: 'user',
              attributes: ['user_id', 'name', 'avatar', 'role'],
            },
          ],
        },
        {
          model: User,
          as: 'creator',
          attributes: ['user_id', 'name', 'avatar', 'role'],
        },
      ],
    });

    debugLog('✅ Direct room created successfully');
    invalidateUserRoomsCache(String(userId1));
    invalidateUserRoomsCache(String(userId2));
    return res.status(201).json({
      success: true,
      data: roomWithMembers,
      isNew: true,
    });
  } catch (error: any) {
    console.error('❌ Error creating/finding direct room:', error);
    return res.status(500).json({ success: false, message: error.message });
  }
});

// Get all users (for chat contact list)
router.get('/users', async (req, res) => {
  try {
    debugLog('📥 GET /api/chat/users - Request received');
    const { role } = req.query; // Optional filter by role
    
    const where: any = {};
    if (role) {
      where.role = role;
    }

    const users = await User.findAll({
      where,
      attributes: ['user_id', 'name', 'avatar', 'role', 'status', 'email'],
      order: [['name', 'ASC']],
    });

    debugLog(`✅ Found ${users.length} users`);
    return res.json({ success: true, data: users });
  } catch (error: any) {
    console.error('❌ Error fetching users:', error);
    return res.status(500).json({ success: false, message: error.message });
  }
});

const STAFF_ROLES = [
  'admin',
  'teacher',
  'super_administrator',
  'เจ้าหน้าที่',
  'administrator',
  'proctor',
  'staff',
];

// Get users by role filter (for permission-based access)
router.get('/users/filter', async (req, res) => {
  try {
    debugLog('📥 GET /api/chat/users/filter - Request received');
    const { requesterRole } = req.query;
    const roleKey = String(requesterRole || 'all');
    const cacheKey = `users:filter:${roleKey}`;

    if (usersFilterCache.isFresh(cacheKey)) {
      debugLog(`✅ Cache hit users/filter role=${roleKey}`);
      return res.json({ success: true, data: usersFilterCache.get(cacheKey) });
    }

    let where: any = {};
    if (requesterRole === 'student') {
      where.role = { [Op.in]: STAFF_ROLES };
    } else {
      // admin/super_admin — ไม่ดึงนักเรียนทั้งระบบ (DB remote ช้ามาก ทำให้ server ค้าง)
      where.role = { [Op.in]: STAFF_ROLES };
    }

    const stale = usersFilterCache.getStale(cacheKey);
    if (stale) {
      debugLog(`⚡ Stale cache users/filter role=${roleKey} — refresh in background`);
      User.findAll({
        where,
        attributes: ['user_id', 'name', 'avatar', 'role', 'status', 'email'],
        order: [['name', 'ASC']],
      })
        .then((users) => usersFilterCache.set(cacheKey, users))
        .catch((err) => console.error('❌ Background users/filter refresh failed:', err));
      return res.json({ success: true, data: stale });
    }

    const users = await User.findAll({
      where,
      attributes: ['user_id', 'name', 'avatar', 'role', 'status', 'email'],
      order: [['name', 'ASC']],
    });

    debugLog(`✅ Found ${users.length} users for role: ${requesterRole}`);
    usersFilterCache.set(cacheKey, users);
    return res.json({ success: true, data: users });
  } catch (error: any) {
    console.error('❌ Error fetching filtered users:', error);
    return res.status(500).json({ success: false, message: error.message });
  }
});

export default router;
