import { Request, Response } from 'express';
import { messengerService } from '../services/messengerService';
import { AuthenticatedRequest } from '../types/auth';
import { getIo } from '../socket/socketManager';
import path from 'path';

class MessengerController {
  async getRooms(req: Request, res: Response) {
    try {
      const user = (req as AuthenticatedRequest).user!;
      const rooms = await messengerService.getRooms(user.userId, user.companyCode!);
      res.json({ success: true, data: rooms });
    } catch (error) {
      const err = error as Error;
      console.error('getRooms error:', err.message);
      res.status(500).json({ success: false, message: err.message });
    }
  }

  async createRoom(req: Request, res: Response) {
    try {
      const user = (req as AuthenticatedRequest).user!;
      const room_type = req.body.room_type ?? req.body.type;
      const room_name = req.body.room_name ?? req.body.name;
      const participant_ids = req.body.participant_ids ?? req.body.participantIds;

      if (!room_type || !participant_ids || !Array.isArray(participant_ids)) {
        return res.status(400).json({ success: false, message: 'room_type and participant_ids are required.' });
      }

      const room = await messengerService.createRoom(user.userId, user.companyCode!, {
        room_type,
        room_name,
        participant_ids,
      });
      res.json({ success: true, data: room });
    } catch (error) {
      const err = error as Error;
      console.error('createRoom error:', err.message);
      res.status(500).json({ success: false, message: err.message });
    }
  }

  async getMessages(req: Request, res: Response) {
    try {
      const user = (req as AuthenticatedRequest).user!;
      const roomId = parseInt(req.params.roomId, 10);
      const limit = parseInt(req.query.limit as string, 10) || 50;
      const before = req.query.before ? parseInt(req.query.before as string, 10) : undefined;

      const messages = await messengerService.getMessages(roomId, user.userId, user.companyCode!, limit, before);
      res.json({ success: true, data: messages });
    } catch (error) {
      const err = error as Error;
      console.error('getMessages error:', err.message);
      res.status(500).json({ success: false, message: err.message });
    }
  }

  async sendMessage(req: Request, res: Response) {
    try {
      const user = (req as AuthenticatedRequest).user!;
      const roomId = parseInt(req.params.roomId, 10);
      const content = req.body.content;
      const messageType = req.body.type ?? req.body.message_type ?? 'text';
      const parentId = req.body.parentId ?? req.body.parent_message_id ?? null;

      if (!content) {
        return res.status(400).json({ success: false, message: 'content is required.' });
      }

      const message = await messengerService.sendMessage(roomId, user.userId, user.companyCode!, content, messageType, parentId);

      // Broadcast to all room participants via Socket.IO
      const io = getIo();
      if (io) {
        io.to(`${user.companyCode}:${roomId}`).emit('new_message', message);
      }

      res.json({ success: true, data: message });
    } catch (error) {
      const err = error as Error;
      console.error('sendMessage error:', err.message);
      res.status(500).json({ success: false, message: err.message });
    }
  }

  async markAsRead(req: Request, res: Response) {
    try {
      const user = (req as AuthenticatedRequest).user!;
      const roomId = parseInt(req.params.roomId, 10);
      await messengerService.markAsRead(roomId, user.userId);
      res.json({ success: true });
    } catch (error) {
      const err = error as Error;
      console.error('markAsRead error:', err.message);
      res.status(500).json({ success: false, message: err.message });
    }
  }

  async uploadFile(req: Request, res: Response) {
    try {
      const user = (req as AuthenticatedRequest).user!;
      const files = req.files as Express.Multer.File[];

      if (!files || files.length === 0) {
        return res.status(400).json({ success: false, message: 'No files uploaded.' });
      }

      const roomId = parseInt(req.body.room_id, 10);
      if (!roomId) {
        return res.status(400).json({ success: false, message: 'room_id is required.' });
      }

      const io = getIo();
      const savedFiles = [];
      for (const file of files) {
        // Use a readable placeholder as content to avoid filename encoding issues
        const isImage = file.mimetype.startsWith('image/');
        const content = isImage ? '[이미지]' : '[파일]';

        // Create a file message
        const message = await messengerService.sendMessage(
          roomId,
          user.userId,
          user.companyCode!,
          content,
          'file'
        );

        const savedFile = await messengerService.saveFile(message.id, {
          originalName: file.originalname,
          storedName: file.filename,
          filePath: file.path,
          fileSize: file.size,
          mimeType: file.mimetype,
        });

        message.files = [savedFile];

        // Broadcast to room so recipients receive it in real-time
        io.to(`${user.companyCode}:${roomId}`).emit('new_message', message);

        savedFiles.push({ message, file: savedFile });
      }

      res.json({ success: true, data: savedFiles });
    } catch (error) {
      const err = error as Error;
      console.error('uploadFile error:', err.message);
      res.status(500).json({ success: false, message: err.message });
    }
  }

  async downloadFile(req: Request, res: Response) {
    try {
      const fileId = parseInt(req.params.fileId, 10);
      const file = await messengerService.getFileById(fileId);

      if (!file) {
        return res.status(404).json({ success: false, message: 'File not found.' });
      }

      res.download(file.file_path, file.original_name);
    } catch (error) {
      const err = error as Error;
      console.error('downloadFile error:', err.message);
      res.status(500).json({ success: false, message: err.message });
    }
  }

  async getCompanyUsers(req: Request, res: Response) {
    try {
      const user = (req as AuthenticatedRequest).user!;
      const users = await messengerService.getCompanyUsers(user.companyCode!, user.userId);
      res.json({ success: true, data: users });
    } catch (error) {
      const err = error as Error;
      console.error('getCompanyUsers error:', err.message);
      res.status(500).json({ success: false, message: err.message });
    }
  }

  async updateRoom(req: Request, res: Response) {
    try {
      const user = (req as AuthenticatedRequest).user!;
      const roomId = parseInt(req.params.roomId, 10);
      const { room_name } = req.body;

      if (!room_name) {
        return res.status(400).json({ success: false, message: 'room_name is required.' });
      }

      const room = await messengerService.updateRoom(roomId, user.companyCode!, room_name);
      if (!room) {
        return res.status(404).json({ success: false, message: 'Room not found.' });
      }

      res.json({ success: true, data: room });
    } catch (error) {
      const err = error as Error;
      console.error('updateRoom error:', err.message);
      res.status(500).json({ success: false, message: err.message });
    }
  }

  async getUnreadCount(req: Request, res: Response) {
    try {
      const user = (req as AuthenticatedRequest).user!;
      const count = await messengerService.getUnreadCount(user.userId, user.companyCode!);
      res.json({ success: true, data: { unread_count: count } });
    } catch (error) {
      const err = error as Error;
      console.error('getUnreadCount error:', err.message);
      res.status(500).json({ success: false, message: err.message });
    }
  }
}

export const messengerController = new MessengerController();
