const { spawn } = require('child_process');
const path = require('path');
const fs = require('fs');
const sharp = require('sharp');
const ChatMessage = require('../models/chatSchema');

exports.saveMessage = async (req, res) => {
  const { meetingId, message, type } = req.body;
  const chat = await Chat.create({
    meetingId,
    message,
    type,
    sender: req.user.id,
  });
  res.json(chat);
};

exports.getMessages = async (req, res) => {
  const { meetingId } = req.params;
  const messages = await Chat.find({ meetingId }).populate('sender');
  res.json(messages);
};

// Ensure upload directory exists
const ensureUploadDir = (dir) => {
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }
};

// Generate thumbnail for images
const generateImageThumbnail = async (filePath, filename) => {
  try {
    const thumbnailDir = path.join(__dirname, '../uploads/chat/thumbnails');
    ensureUploadDir(thumbnailDir);

    const thumbnailName = `thumb_${filename.replace(/\.[^.]+$/, '.jpg')}`;
    const thumbnailPath = path.join(thumbnailDir, thumbnailName);

    await sharp(filePath)
      .resize(300, 300, {
        fit: 'inside',
        withoutEnlargement: true
      })
      .jpeg({ quality: 80 })
      .toFile(thumbnailPath);

    return thumbnailName;
  } catch (error) {
    console.error('Error generating image thumbnail:', error);
    return null;
  }
};

// Generate thumbnail for videos
const generateVideoThumbnail = (filePath, filename) => {
  return new Promise((resolve) => {
    try {
      const thumbnailDir = path.join(__dirname, '../uploads/chat/thumbnails');
      const thumbnailName = `thumb_${filename.replace(/\.[^.]+$/, '.jpg')}`;
      const thumbnailPath = path.join(thumbnailDir, thumbnailName);

      const ffmpeg = spawn('ffmpeg', [
        '-i', filePath,
        '-ss', '00:00:01',
        '-vframes', '1',
        '-s', '300x300',
        '-y', // Overwrite output file
        thumbnailPath
      ]);

      ffmpeg.on('close', (code) => {
        if (code === 0) {
          resolve(thumbnailName);
        } else {
          console.error('FFmpeg process failed with code:', code);
          resolve(null);
        }
      });

      ffmpeg.on('error', (error) => {
        console.error('FFmpeg spawn error:', error);
        resolve(null);
      });

    } catch (error) {
      console.error('Video thumbnail generation failed:', error);
      resolve(null);
    }
  });
};

// Determine file type based on MIME type
const getFileType = (mimeType) => {
  if (mimeType.startsWith('image/')) return 'image';
  if (mimeType.startsWith('video/')) return 'video';
  if (mimeType.includes('pdf')) return 'document';
  if (mimeType.includes('word') || mimeType.includes('document')) return 'document';
  if (mimeType.includes('sheet') || mimeType.includes('excel')) return 'document';
  if (mimeType.includes('presentation') || mimeType.includes('powerpoint')) return 'document';
  return 'document';
};

// const saveTextMessage = async (req, res) => {
//   try {
//     const { meetingId, senderName, senderRole, textContent, jitsiMessageId, jitsiFrom, messageHash } = req.body;

//     if (!meetingId || !senderName || !textContent) {
//       return res.status(400).json({
//         success: false,
//         error: 'Meeting ID, sender name, and text content are required'
//       });
//     }

//     const existingMessage = await ChatMessage.findOne({
//       $or: [
//         { messageHash },
//         {
//           meetingId,
//           jitsiFrom,
//           textContent: textContent.trim(),
//           createdAt: {
//             $gte: new Date(Date.now() - 30000) // Within last 30 seconds
//           }
//         }
//       ]
//     });

//     if (existingMessage) {
//       console.log('Duplicate message detected, returning existing:', existingMessage._id);
//       return res.status(200).json({
//         success: true,
//         message: 'Message already exists',
//         data: existingMessage.toClientFormat(),
//         duplicate: true
//       });
//     }

//     const chatMessage = new ChatMessage({
//       meetingId,
//       senderId: req.user?.id || null,
//       senderName,
//       senderRole: senderRole || 'participant',
//       messageType: 'text',
//       textContent: textContent.trim(),
//       jitsiMessageId,
//       jitsiFrom,
//       messageHash,
//       status: 'sent'
//     });

//     const savedMessage = await chatMessage.save();
//     console.log('✅ New text message saved:', savedMessage._id);

//     res.status(200).json({
//       success: true,
//       message: 'Text message saved successfully',
//       data: savedMessage.toClientFormat(),
//       duplicate: false
//     });

//   } catch (error) {
//     console.error('❌ Error saving text message:', error);
//     res.status(500).json({
//       success: false,
//       error: 'Failed to save text message'
//     });
//   }
// };
// Enhanced backend controller with consistent hash generation
const saveTextMessage = async (req, res) => {
  try {
    const {
      meetingId,
      senderName,
      senderRole,
      textContent,
      jitsiFrom,
      jitsiTimestamp
    } = req.body;

    if (!meetingId || !senderName || !textContent) {
      return res.status(400).json({
        success: false,
        error: 'Meeting ID, sender name, and text content are required'
      });
    }

    // Generate consistent hash (same logic as frontend)
    const timestamp = jitsiTimestamp || Date.now();
    const normalizedTimestamp = Math.floor(timestamp / 30000);
    const normalizedText = textContent.substring(0, 100).replace(/\s+/g, ' ').trim();
    const messageHash = `${senderName}-${normalizedText}-${normalizedTimestamp}`;

    console.log(`💾 Attempting to save message with hash: ${messageHash}`);

    // Check for existing message with same hash
    const existingMessage = await ChatMessage.findOne({
      messageHash: messageHash
    });

    if (existingMessage) {
      console.log('🔍 Duplicate message found in database:', existingMessage._id);
      return res.status(200).json({
        success: true,
        message: 'Message already exists',
        data: existingMessage.toClientFormat(),
        duplicate: true
      });
    }

    // Save new message
    const chatMessage = new ChatMessage({
      meetingId,
      senderName,
      senderRole: senderRole || 'participant',
      messageType: 'text',
      textContent: textContent.trim(),
      messageHash,
      jitsiFrom: jitsiFrom || 'backend',
      jitsiTimestamp: timestamp,
      messageSource: 'backend_api',
      status: 'sent'
    });

    const savedMessage = await chatMessage.save();
    console.log('✅ New text message saved with hash:', messageHash);

    res.status(200).json({
      success: true,
      message: 'Text message saved successfully',
      data: savedMessage.toClientFormat(),
      duplicate: false
    });

  } catch (error) {
    if (error.code === 11000) {
      console.log('🔍 Duplicate message caught by database constraint');
      const existingMessage = await ChatMessage.findOne({
        meetingId: req.body.meetingId,
        messageHash: req.body.messageHash || `${req.body.senderName}-${req.body.textContent.substring(0, 100)}-${Math.floor(Date.now() / 30000)}`
      });

      return res.status(200).json({
        success: true,
        message: 'Message already exists',
        data: existingMessage ? existingMessage.toClientFormat() : null,
        duplicate: true
      });
    }

    console.error('❌ Error saving text message:', error);
    res.status(500).json({
      success: false,
      error: 'Failed to save text message'
    });
  }
};


// Upload file controller
const uploadFile = async (req, res) => {
  try {
    console.log('📤 File upload request received');

    // Validate file
    if (!req.file) {
      return res.status(400).json({
        success: false,
        error: 'No file uploaded'
      });
    }

    // Validate required fields
    const { meetingId, senderName, senderRole = 'participant' } = req.body;

    if (!meetingId || !senderName) {
      // Clean up uploaded file if validation fails
      if (fs.existsSync(req.file.path)) {
        fs.unlinkSync(req.file.path);
      }
      return res.status(400).json({
        success: false,
        error: 'Meeting ID and sender name are required'
      });
    }

    const file = req.file;
    const fileName = file.originalname;
    const filePath = file.path;
    const fileSize = file.size;
    const mimeType = file.mimetype;
    const uniqueFileName = file.filename;

    console.log(`📁 Processing file: ${fileName} (${fileSize} bytes)`);

    // Determine file type
    const fileType = getFileType(mimeType);

    // Generate file URLs
    const baseUrl = process.env.BASE_URL || 'http://localhost:5000';
    const fileUrl = `${baseUrl}/uploads/chat/${uniqueFileName}`;

    // Generate thumbnail if needed
    let thumbnailUrl = null;
    try {
      if (fileType === 'image') {
        console.log('🖼️ Generating image thumbnail...');
        const thumbnailName = await generateImageThumbnail(filePath, uniqueFileName);
        if (thumbnailName) {
          thumbnailUrl = `${baseUrl}/uploads/chat/thumbnails/${thumbnailName}`;
        }
      } else if (fileType === 'video') {
        console.log('🎥 Generating video thumbnail...');
        const thumbnailName = await generateVideoThumbnail(filePath, uniqueFileName);
        if (thumbnailName) {
          thumbnailUrl = `${baseUrl}/uploads/chat/thumbnails/${thumbnailName}`;
        }
      }
    } catch (thumbnailError) {
      console.error('Thumbnail generation failed:', thumbnailError);
      // Continue without thumbnail
    }

    // Save to database
    const chatMessage = new ChatMessage({
      meetingId,
      senderId: req.user?.id || null,
      senderName,
      senderRole,
      messageType: fileType,
      content: fileName,
      fileUrl,
      fileName,
      fileSize,
      mimeType,
      thumbnailUrl,
      status: 'sent',
      createdAt: new Date()
    });

    const savedMessage = await chatMessage.save();
    console.log('✅ File saved to database:', savedMessage._id);

    // Return success response
    res.status(200).json({
      success: true,
      message: 'File uploaded successfully',
      data: {
        messageId: savedMessage._id,
        fileUrl,
        fileName,
        fileSize,
        mimeType,
        fileType,
        thumbnailUrl,
        uploadedAt: new Date().toISOString()
      }
    });

  } catch (error) {
    console.error('❌ Upload error:', error);

    // Clean up uploaded file on error
    if (req.file && fs.existsSync(req.file.path)) {
      try {
        fs.unlinkSync(req.file.path);
      } catch (cleanupError) {
        console.error('Failed to clean up file:', cleanupError);
      }
    }

    res.status(500).json({
      success: false,
      error: 'File upload failed',
      details: process.env.NODE_ENV === 'development' ? error.message : undefined
    });
  }
};

// Get chat messages for a meeting
const getChatMessages = async (req, res) => {
  try {
    const { meetingId } = req.params;
    const { limit = 50, offset = 0 } = req.query;

    if (!meetingId) {
      return res.status(400).json({
        success: false,
        error: 'Meeting ID is required'
      });
    }

    const messages = await ChatMessage.find({ meetingId })
      .sort({ createdAt: 1 })
      .limit(parseInt(limit))
      .skip(parseInt(offset));

    const formattedMessages = messages.map(msg => ({
      id: msg._id,
      from: msg.senderName,
      type: msg.messageType === 'text' ? 'text' : 'file',
      text: msg.messageType === 'text' ? msg.textContent : `📎 ${msg.fileName}`,
      fileData: msg.messageType !== 'text' ? {
        type: msg.messageType,
        name: msg.fileName,
        size: msg.fileSize,
        mime: msg.mimeType,
        url: msg.fileUrl,
        thumbnailUrl: msg.thumbnailUrl
      } : null,
      time: msg.createdAt,
      senderRole: msg.senderRole,
      messageHash: msg.messageHash,
      jitsiFrom: msg.jitsiFrom,
    }));

    res.json({
      success: true,
      messages: formattedMessages,
      total: messages.length
    });

  } catch (error) {
    console.error('Error fetching chat messages:', error);
    res.status(500).json({
      success: false,
      error: 'Failed to fetch messages'
    });
  }
};

module.exports = {
  uploadFile,
  getChatMessages,
  saveTextMessage,
};

