const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const mime = require('mime-types');
const Database = require('../database/database');
const router = express.Router();

const db = new Database();

// Configure multer for file uploads
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const uploadDir = path.join(__dirname, '../uploads');
    if (!fs.existsSync(uploadDir)) {
      fs.mkdirSync(uploadDir, { recursive: true });
    }
    cb(null, uploadDir);
  },
  filename: (req, file, cb) => {
    // Generate unique filename
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    const ext = path.extname(file.originalname);
    cb(null, file.fieldname + '-' + uniqueSuffix + ext);
  }
});

// File filter for security
const fileFilter = (req, file, cb) => {
  // Allow images, documents, and common file types
  const allowedTypes = [
    'image/jpeg', 'image/png', 'image/gif', 'image/webp',
    'application/pdf', 'text/plain', 'application/msword',
    'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    'application/vnd.ms-excel',
    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
  ];
  
  if (allowedTypes.includes(file.mimetype)) {
    cb(null, true);
  } else {
    cb(new Error('File type not allowed'), false);
  }
};

const upload = multer({ 
  storage: storage,
  fileFilter: fileFilter,
  limits: {
    fileSize: 10 * 1024 * 1024 // 10MB limit
  }
});

// Middleware to check authentication
const requireAuth = (req, res, next) => {
  if (req.isAuthenticated()) {
    return next();
  }
  res.status(401).json({ error: 'Authentication required' });
};

// Get recent messages
router.get('/messages', requireAuth, async (req, res) => {
  try {
    const limit = parseInt(req.query.limit) || 50;
    const messages = await db.getRecentMessages(limit);
    
    // Format messages for frontend
    const formattedMessages = messages.map(msg => ({
      id: msg.id,
      content: msg.content,
      timestamp: msg.timestamp,
      messageType: msg.message_type,
      files: msg.files || [],
      user: {
        id: msg.user_id,
        name: msg.name,
        avatar: msg.avatar
      }
    }));
    
    res.json(formattedMessages);
  } catch (error) {
    console.error('Error fetching messages:', error);
    res.status(500).json({ error: 'Failed to fetch messages' });
  }
});

// Upload file
router.post('/upload', requireAuth, upload.single('file'), async (req, res) => {
  try {
    if (!req.file) {
      return res.status(400).json({ error: 'No file uploaded' });
    }

    const { message } = req.body;
    const user = req.user;

    // Save message
    const savedMessage = await db.saveMessage({
      userId: user.id,
      content: message || '',
      timestamp: new Date().toISOString(),
      messageType: 'file'
    });

    // Save file info
    const savedFile = await db.saveFile({
      messageId: savedMessage.id,
      filename: req.file.filename,
      originalName: req.file.originalname,
      filePath: req.file.path,
      fileSize: req.file.size,
      mimeType: req.file.mimetype
    });

    // Return formatted response
    const messageData = {
      id: savedMessage.id,
      content: savedMessage.content,
      timestamp: savedMessage.timestamp,
      messageType: savedMessage.message_type,
      files: [savedFile],
      user: {
        id: user.id,
        name: user.name,
        avatar: user.avatar
      }
    };

    res.json({ message: messageData });
  } catch (error) {
    console.error('Error uploading file:', error);
    res.status(500).json({ error: 'Failed to upload file' });
  }
});

// Download file
router.get('/download/:filename', requireAuth, (req, res) => {
  try {
    const filename = req.params.filename;
    const filePath = path.join(__dirname, '../uploads', filename);
    
    // Check if file exists
    if (!fs.existsSync(filePath)) {
      return res.status(404).json({ error: 'File not found' });
    }
    
    // Set appropriate headers
    const mimeType = mime.lookup(filePath) || 'application/octet-stream';
    res.setHeader('Content-Type', mimeType);
    res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
    
    // Stream the file
    const fileStream = fs.createReadStream(filePath);
    fileStream.pipe(res);
  } catch (error) {
    console.error('Error downloading file:', error);
    res.status(500).json({ error: 'Failed to download file' });
  }
});

// Private chat endpoints

// Get all users for starting private chats
router.get('/users', requireAuth, async (req, res) => {
  try {
    const users = await db.getAllUsers(req.user.id);
    res.json({ users });
  } catch (error) {
    console.error('Error fetching users:', error);
    res.status(500).json({ error: 'Failed to fetch users' });
  }
});

// Create or get private chat
router.post('/private-chat', requireAuth, async (req, res) => {
  try {
    const { otherUserId } = req.body;
    
    if (!otherUserId || otherUserId == req.user.id) {
      return res.status(400).json({ success: false, message: 'Invalid user ID' });
    }
    
    const privateChat = await db.createOrGetPrivateChat(req.user.id, otherUserId);
    res.json({ 
      success: true, 
      chatId: privateChat.id,
      privateChat: privateChat 
    });
  } catch (error) {
    console.error('Error creating/getting private chat:', error);
    res.status(500).json({ success: false, message: 'Failed to create private chat' });
  }
});

// Get user's private chats
router.get('/private-chats', requireAuth, async (req, res) => {
  try {
    const privateChats = await db.getUserPrivateChats(req.user.id);
    res.json({ privateChats });
  } catch (error) {
    console.error('Error fetching private chats:', error);
    res.status(500).json({ error: 'Failed to fetch private chats' });
  }
});

// Get private chat messages
router.get('/private-chat/:chatId/messages', requireAuth, async (req, res) => {
  try {
    const { chatId } = req.params;
    const messages = await db.getPrivateChatMessages(chatId);
    res.json({ messages });
  } catch (error) {
    console.error('Error fetching private chat messages:', error);
    res.status(500).json({ error: 'Failed to fetch messages' });
  }
});

// Send private message
router.post('/private-message', requireAuth, async (req, res) => {
  try {
    const { privateChatId, content, messageType = 'text' } = req.body;
    
    if (!privateChatId || !content) {
      return res.status(400).json({ error: 'Private chat ID and content are required' });
    }
    
    const messageData = {
      userId: req.user.id,
      content,
      timestamp: new Date().toISOString(),
      messageType,
      privateChatId
    };
    
    const savedMessage = await db.saveMessage(messageData);
    
    // Get user info for the message
    const user = await db.getUserById(req.user.id);
    const messageWithUser = {
      ...savedMessage,
      name: user.name,
      avatar: user.avatar
    };
    
    res.json({ message: messageWithUser });
  } catch (error) {
    console.error('Error sending private message:', error);
    res.status(500).json({ error: 'Failed to send message' });
  }
});

// Upload file for private chat
router.post('/private-upload', requireAuth, upload.single('file'), async (req, res) => {
  try {
    const { privateChatId, message: messageText } = req.body;
    
    if (!privateChatId) {
      return res.status(400).json({ error: 'Private chat ID is required' });
    }
    
    if (!req.file) {
      return res.status(400).json({ error: 'No file uploaded' });
    }
    
    // Save message to database
    const messageData = {
      userId: req.user.id,
      content: messageText || `Shared a file: ${req.file.originalname}`,
      timestamp: new Date().toISOString(),
      messageType: 'file',
      privateChatId
    };
    
    const savedMessage = await db.saveMessage(messageData);
    
    // Save file info
    const fileData = {
      messageId: savedMessage.id,
      filename: req.file.filename,
      originalName: req.file.originalname,
      filePath: req.file.path,
      fileSize: req.file.size,
      mimeType: req.file.mimetype
    };
    
    await db.saveFile(fileData);
    
    // Get user info for the response
    const user = await db.getUserById(req.user.id);
    const messageWithUser = {
      ...savedMessage,
      name: user.name,
      avatar: user.avatar,
      files: [fileData]
    };
    
    res.json({ message: messageWithUser });
  } catch (error) {
    console.error('Error uploading file for private chat:', error);
    res.status(500).json({ error: 'Failed to upload file' });
  }
});

module.exports = router;