const express = require('express');
const http = require('http');
const cors = require('cors');
const mongoose = require('mongoose');
const path = require('path');
const fs = require('fs');
const compression = require('compression');
const connectDB = require('./utils/db');
const userRoutes = require('./routes/userRoutes');
const authRoutes = require('./routes/authRoutes');
const adminAuthRoutes = require('./routes/adminAuthRoutes');
const postRoutes = require('./routes/postRoutes');
const personalDetailsRoutes = require('./routes/personalDetailsRoutes');
const schoolDetailsRoutes = require('./routes/schoolDetailsRoutes');
const schoolDetailsWithoutCurrentClassRoutes = require('./routes/schoolDetailsWithoutCurrentClassRoutes');
const graduateDetailsRoutes = require('./routes/graduateDetailsRoutes');
const schoolRoutes = require('./routes/schoolRoutes');
const collegeRoutes = require('./routes/collegeRoutes');
const workingProfessionalRoutes = require('./routes/workingProfessionalRoutes');
const businessRoutes = require('./routes/businessRoutes');
const careerRoutes = require('./routes/careerRoutes');
const examRoutes = require('./routes/examRoutes');
const quizRoutes = require('./routes/quizRoutes');
const studyGroupRoutes = require('./routes/studyGroupRoutes');
const portfolioRoutes = require('./routes/portfolioRoutes');
const careerPathRoutes = require('./routes/careerPathRoutes');
const certificationRoutes = require('./routes/certificationRoutes');
const mentorRoutes = require('./routes/mentorRoutes');
const careerAnalyticsRoutes = require('./routes/careerAnalyticsRoutes');
const decisionTreeRoutes = require('./routes/decisionTreeRoutes');
const freeEducationRoutes = require('./routes/freeEducationRoutes');
const collegeEligibilityRoutes = require('./routes/collegeEligibilityRoutes');
const jobVsPGRoutes = require('./routes/jobVsPGRoutes');
const careerProgressionRoutes = require('./routes/careerProgressionRoutes');
const industryAnalysisRoutes = require('./routes/industryAnalysisRoutes');
const portfolioAnalysisRoutes = require('./routes/portfolioAnalysisRoutes');
const interestsRoutes = require('./routes/interestsRoutes');
const newsRoutes = require('./routes/newsRoutes');
const groupRoutes = require('./routes/groupRoutes');
const groupMessageRoutes = require('./routes/groupMessageRoutes');
const cutsRoutes = require('./routes/cutsRoutes');
const followerRoutes = require('./routes/followerRoutes');
const notificationRoutes = require('./routes/notificationRoutes');
const WebSocketServer = require('./websocketServer');
const GroupChatWebSocket = require('./websocketGroupChat');
require('dotenv').config();

const app = express();
const server = http.createServer(app);
const PORT = process.env.PORT || 5500;

// Initialize WebSocket Servers with proper error handling
let wsServer, groupChatWS;

try {
    console.log('🔌 [WEBSOCKET] Initializing WebSocket servers...');
    
    // Initialize AI Chat WebSocket Server
    wsServer = new WebSocketServer(server);
    console.log('✅ [WEBSOCKET] AI Chat WebSocket server initialized on /ws');
    
    // Initialize Group Chat WebSocket Server
    groupChatWS = new GroupChatWebSocket(server);
    console.log('✅ [WEBSOCKET] Group Chat WebSocket server initialized on /ws/group-chat');
    
    // Set up graceful shutdown for WebSocket servers
    process.on('SIGINT', () => {
        console.log('🔄 [WEBSOCKET] Shutting down WebSocket servers...');
        if (wsServer) {
            wsServer.wss.close();
            console.log('✅ [WEBSOCKET] AI Chat WebSocket server closed');
        }
        if (groupChatWS) {
            groupChatWS.wss.close();
            console.log('✅ [WEBSOCKET] Group Chat WebSocket server closed');
        }
        process.exit(0);
    });
    
} catch (error) {
    console.error('❌ [WEBSOCKET] Failed to initialize WebSocket servers:', error);
    console.error('❌ [WEBSOCKET] Server will continue without WebSocket functionality');
}

// Connect to MongoDB
connectDB()
    .then(() => {
        console.log('✅ Database connection established');
    })
    .catch((error) => {
        console.error('❌ Database connection failed:', error.message);
        process.exit(1);
    });

// Basic middleware
app.use(cors());

// Enable compression for all responses
app.use(compression({
    level: 6, // Compression level (1-9, 6 is good balance)
    threshold: 1024, // Only compress responses larger than 1KB
    filter: (req, res) => {
        // Don't compress if client doesn't support it
        if (req.headers['x-no-compression']) {
            return false;
        }
        // Use compression filter
        return compression.filter(req, res);
    }
}));

// Increase request size limits for larger payloads
app.use(express.json({ 
    limit: '50mb', // Increased from 1mb to 50mb
    parameterLimit: 50000 // Increase parameter limit
}));
app.use(express.urlencoded({ 
    limit: '50mb', 
    extended: true,
    parameterLimit: 50000 
}));

// Serve profile images directly
app.get('/uploads/profiles/:filename', (req, res) => {
    try {
        const { filename } = req.params;
        console.log(`🖼️ [PROFILE IMAGE SERVE DEBUG] Requested profile image: ${filename}`);
        
        // Construct file path
        const filePath = path.join(__dirname, 'uploads', 'profiles', filename);
        console.log(`🖼️ [PROFILE IMAGE SERVE DEBUG] File path: ${filePath}`);
        
        // Check if file exists
        if (!fs.existsSync(filePath)) {
            console.log(`❌ [PROFILE IMAGE SERVE DEBUG] Profile image not found: ${filename}`);
            return res.status(404).json({
                success: false,
                message: 'Profile image not found',
                filename: filename
            });
        }
        
        // Get file stats
        const stats = fs.statSync(filePath);
        console.log(`🖼️ [PROFILE IMAGE SERVE DEBUG] Profile image found - Size: ${stats.size} bytes, Modified: ${stats.mtime}`);
        
        // Set appropriate headers for profile images
        const ext = path.extname(filename).toLowerCase();
        const mimeTypes = {
            '.jpg': 'image/jpeg',
            '.jpeg': 'image/jpeg',
            '.png': 'image/png',
            '.webp': 'image/webp'
        };
        
        const mimeType = mimeTypes[ext] || 'image/jpeg';
        res.setHeader('Content-Type', mimeType);
        res.setHeader('Content-Length', stats.size);
        res.setHeader('Cache-Control', 'public, max-age=31536000'); // Cache for 1 year
        
        console.log(`✅ [PROFILE IMAGE SERVE DEBUG] Serving profile image with MIME type: ${mimeType}`);
        
        // Send the file
        res.sendFile(filePath);
        
    } catch (error) {
        console.error(`❌ [PROFILE IMAGE SERVE ERROR] Error serving profile image:`, error);
        res.status(500).json({
            success: false,
            message: 'Error serving profile image',
            error: error.message
        });
    }
});

// Serve uploaded files directly
app.get('/uploads/posts/:filename', (req, res) => {
    try {
        const { filename } = req.params;
        console.log(`📁 [FILE SERVE DEBUG] Requested file: ${filename}`);
        
        // Construct file path
        const filePath = path.join(__dirname, 'uploads', 'posts', filename);
        console.log(`📁 [FILE SERVE DEBUG] File path: ${filePath}`);
        
        // Check if file exists
        if (!fs.existsSync(filePath)) {
            console.log(`❌ [FILE SERVE DEBUG] File not found: ${filename}`);
            return res.status(404).json({
                success: false,
                message: 'File not found',
                filename: filename
            });
        }
        
        // Get file stats
        const stats = fs.statSync(filePath);
        console.log(`📁 [FILE SERVE DEBUG] File found - Size: ${stats.size} bytes, Modified: ${stats.mtime}`);
        
        // Set appropriate headers
        const ext = path.extname(filename).toLowerCase();
        const mimeTypes = {
            '.jpg': 'image/jpeg',
            '.jpeg': 'image/jpeg',
            '.png': 'image/png',
            '.gif': 'image/gif',
            '.webp': 'image/webp',
            '.bmp': 'image/bmp',
            '.tiff': 'image/tiff',
            '.svg': 'image/svg+xml',
            '.mp4': 'video/mp4',
            '.avi': 'video/avi',
            '.mov': 'video/quicktime',
            '.wmv': 'video/x-ms-wmv',
            '.flv': 'video/x-flv',
            '.webm': 'video/webm'
        };
        
        const mimeType = mimeTypes[ext] || 'application/octet-stream';
        res.setHeader('Content-Type', mimeType);
        res.setHeader('Content-Length', stats.size);
        res.setHeader('Cache-Control', 'public, max-age=31536000'); // Cache for 1 year
        
        console.log(`✅ [FILE SERVE DEBUG] Serving file with MIME type: ${mimeType}`);
        
        // Send the file
        res.sendFile(filePath);
        
    } catch (error) {
        console.error(`❌ [FILE SERVE ERROR] Error serving file:`, error);
        res.status(500).json({
            success: false,
            message: 'Error serving file',
            error: error.message
        });
    }
});

// Serve cut videos
app.get('/uploads/cuts/:filename', (req, res) => {
    try {
        const { filename } = req.params;
        console.log(`🎬 [CUTS FILE SERVE DEBUG] Requested cut file: ${filename}`);
        
        // Construct file path
        const filePath = path.join(__dirname, 'uploads', 'cuts', filename);
        console.log(`🎬 [CUTS FILE SERVE DEBUG] File path: ${filePath}`);
        
        // Check if file exists
        if (!fs.existsSync(filePath)) {
            console.log(`❌ [CUTS FILE SERVE DEBUG] File not found: ${filename}`);
            return res.status(404).json({
                success: false,
                message: 'Cut file not found',
                filename: filename
            });
        }
        
        // Get file stats
        const stats = fs.statSync(filePath);
        console.log(`🎬 [CUTS FILE SERVE DEBUG] File found - Size: ${(stats.size / 1024 / 1024).toFixed(2)}MB, Modified: ${stats.mtime}`);
        
        // Set appropriate headers for video files
        const ext = path.extname(filename).toLowerCase();
        const mimeTypes = {
            '.mp4': 'video/mp4',
            '.avi': 'video/avi',
            '.mov': 'video/quicktime',
            '.wmv': 'video/x-ms-wmv',
            '.flv': 'video/x-flv',
            '.webm': 'video/webm',
            '.mkv': 'video/x-matroska',
            '.m4v': 'video/x-m4v'
        };
        
        const mimeType = mimeTypes[ext] || 'video/mp4';
        res.setHeader('Content-Type', mimeType);
        res.setHeader('Content-Length', stats.size);
        res.setHeader('Cache-Control', 'public, max-age=31536000'); // Cache for 1 year
        res.setHeader('Accept-Ranges', 'bytes'); // Enable range requests for video streaming
        
        console.log(`✅ [CUTS FILE SERVE DEBUG] Serving cut file with MIME type: ${mimeType}`);
        
        // Send the file
        res.sendFile(filePath);
        
    } catch (error) {
        console.error(`❌ [CUTS FILE SERVE ERROR] Error serving cut file:`, error);
        res.status(500).json({
            success: false,
            message: 'Error serving cut file',
            error: error.message
        });
    }
});

// Serve cut thumbnails
app.get('/uploads/cuts/thumbnails/:filename', (req, res) => {
    try {
        const { filename } = req.params;
        console.log(`🎬 [CUT THUMBNAIL SERVE DEBUG] Requested thumbnail: ${filename}`);
        
        // Construct file path
        const filePath = path.join(__dirname, 'uploads', 'cuts', 'thumbnails', filename);
        console.log(`🎬 [CUT THUMBNAIL SERVE DEBUG] File path: ${filePath}`);
        
        // Check if file exists
        if (!fs.existsSync(filePath)) {
            console.log(`❌ [CUT THUMBNAIL SERVE DEBUG] Thumbnail not found: ${filename}`);
            return res.status(404).json({
                success: false,
                message: 'Cut thumbnail not found',
                filename: filename
            });
        }
        
        // Get file stats
        const stats = fs.statSync(filePath);
        console.log(`🎬 [CUT THUMBNAIL SERVE DEBUG] Thumbnail found - Size: ${(stats.size / 1024).toFixed(2)}KB, Modified: ${stats.mtime}`);
        
        // Set appropriate headers for image files
        const ext = path.extname(filename).toLowerCase();
        const mimeTypes = {
            '.jpg': 'image/jpeg',
            '.jpeg': 'image/jpeg',
            '.png': 'image/png',
            '.webp': 'image/webp'
        };
        
        const mimeType = mimeTypes[ext] || 'image/jpeg';
        res.setHeader('Content-Type', mimeType);
        res.setHeader('Content-Length', stats.size);
        res.setHeader('Cache-Control', 'public, max-age=86400'); // Cache for 24 hours
        
        console.log(`✅ [CUT THUMBNAIL SERVE DEBUG] Serving thumbnail with MIME type: ${mimeType}`);
        
        // Send the file
        res.sendFile(filePath);
        
    } catch (error) {
        console.error(`❌ [CUT THUMBNAIL SERVE ERROR] Error serving thumbnail:`, error);
        res.status(500).json({
            success: false,
            message: 'Error serving cut thumbnail',
            error: error.message
        });
    }
});

// Serve group message media files
app.get('/uploads/group_messages/:filename', (req, res) => {
    try {
        const { filename } = req.params;
        console.log(`💬 [GROUP MESSAGE FILE SERVE DEBUG] Requested file: ${filename}`);
        
        const filePath = path.join(__dirname, 'uploads', 'group_messages', filename);
        console.log(`💬 [GROUP MESSAGE FILE SERVE DEBUG] File path: ${filePath}`);
        
        if (!fs.existsSync(filePath)) {
            console.log(`❌ [GROUP MESSAGE FILE SERVE DEBUG] File not found: ${filename}`);
            return res.status(404).json({
                success: false,
                message: 'Group message file not found',
                filename: filename
            });
        }
        
        const stats = fs.statSync(filePath);
        console.log(`💬 [GROUP MESSAGE FILE SERVE DEBUG] File found - Size: ${(stats.size / 1024 / 1024).toFixed(2)}MB`);
        
        const ext = path.extname(filename).toLowerCase();
        const mimeTypes = {
            '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.png': 'image/png', '.gif': 'image/gif',
            '.webp': 'image/webp', '.bmp': 'image/bmp', '.tiff': 'image/tiff', '.svg': 'image/svg+xml',
            '.mp4': 'video/mp4', '.avi': 'video/avi', '.mov': 'video/quicktime', '.wmv': 'video/x-ms-wmv',
            '.flv': 'video/x-flv', '.webm': 'video/webm', '.mkv': 'video/x-matroska', '.m4v': 'video/x-m4v',
            '.pdf': 'application/pdf', '.doc': 'application/msword', '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            '.txt': 'text/plain', '.csv': 'text/csv'
        };
        
        const mimeType = mimeTypes[ext] || 'application/octet-stream';
        res.setHeader('Content-Type', mimeType);
        res.setHeader('Content-Length', stats.size);
        res.setHeader('Cache-Control', 'public, max-age=31536000');
        
        if (mimeType.startsWith('video/')) {
            res.setHeader('Accept-Ranges', 'bytes');
        }
        
        console.log(`✅ [GROUP MESSAGE FILE SERVE DEBUG] Serving file with MIME type: ${mimeType}`);
        res.sendFile(filePath);
        
    } catch (error) {
        console.error(`❌ [GROUP MESSAGE FILE SERVE ERROR] Error serving file:`, error);
        res.status(500).json({
            success: false,
            message: 'Error serving group message file',
            error: error.message
        });
    }
});

// Handle large payloads gracefully
app.use((req, res, next) => {
    // Set timeout for large requests
    req.setTimeout(300000); // 5 minutes timeout for large requests
    res.setTimeout(300000);
    
    // Log large requests
    const contentLength = req.headers['content-length'];
    if (contentLength && parseInt(contentLength) > 10 * 1024 * 1024) { // > 10MB
        console.log(`📦 Large request detected: ${(parseInt(contentLength) / 1024 / 1024).toFixed(2)}MB`);
    }
    
    next();
});

// Apply sanitization middleware globally
app.use((req, res, next) => {
    // MongoDB injection prevention
    if (req.body) {
        // Remove any keys that start with '$' or contain '.'
        Object.keys(req.body).forEach(key => {
            if (key.startsWith('$') || key.includes('.')) {
                delete req.body[key];
            }
        });
    }
    next();
});

// Health check route
app.get('/health', (req, res) => {
    try {
        const healthStatus = { 
            status: 'ok',
            mongodb: mongoose.connection.readyState === 1 ? 'connected' : 'disconnected',
            timestamp: new Date().toISOString(),
            websockets: {
                aiChat: wsServer ? {
                    status: 'running',
                    path: '/ws',
                    connections: wsServer.getConnectedClientsCount()
                } : { status: 'not_initialized' },
                groupChat: groupChatWS ? {
                    status: 'running',
                    path: '/ws/group-chat',
                    stats: groupChatWS.getStats()
                } : { status: 'not_initialized' }
            }
        };
        
        res.json(healthStatus);
    } catch (error) {
        console.error('Health check error:', error);
        res.status(500).json({
            status: 'error',
            message: 'Health check failed',
            error: error.message
        });
    }
});

// Routes
app.use('/api/users', userRoutes);
app.use('/api/auth', authRoutes);
app.use('/api/admin', adminAuthRoutes);
app.use('/api/posts', postRoutes);
app.use('/api/personal-details', personalDetailsRoutes);
app.use('/api/school-details', schoolDetailsRoutes);
app.use('/api/school-details-without-current-class', schoolDetailsWithoutCurrentClassRoutes);
app.use('/api/graduate-details', graduateDetailsRoutes);
app.use('/api/schools', schoolRoutes);
app.use('/api/colleges', collegeRoutes);
app.use('/api/working-professional', workingProfessionalRoutes);
app.use('/api/business', businessRoutes);
app.use('/api/career', careerRoutes);
app.use('/api/exams', examRoutes);
app.use('/api/quiz', quizRoutes);
app.use('/api/study-groups', studyGroupRoutes);
app.use('/api/portfolio', portfolioRoutes);
app.use('/api/career-paths', careerPathRoutes);
app.use('/api/certifications', certificationRoutes);
app.use('/api/mentors', mentorRoutes);
app.use('/api/analytics', careerAnalyticsRoutes);
app.use('/api/decision-tree', decisionTreeRoutes);
app.use('/api/free-education', freeEducationRoutes);
app.use('/api/college-eligibility', collegeEligibilityRoutes);
app.use('/api/job-vs-pg', jobVsPGRoutes);
app.use('/api/career-progression', careerProgressionRoutes);
app.use('/api/industry-analysis', industryAnalysisRoutes);
app.use('/api/portfolio-analysis', portfolioAnalysisRoutes);
app.use('/api/interests', interestsRoutes);
app.use('/api/news', newsRoutes);
app.use('/api/groups', groupRoutes);
app.use('/api/groups', groupMessageRoutes);
app.use('/api/cuts', cutsRoutes);
app.use('/api/followers', followerRoutes);
app.use('/api/notifications', notificationRoutes);

// Root route
app.get('/', (req, res) => {
    res.send('Backend API is running!');
});

// 404 handler for undefined routes
app.use('*', (req, res) => {
    res.status(404).json({
        success: false,
        message: 'Route not found',
        path: req.originalUrl,
        method: req.method
    });
});

// Error handling middleware
app.use((err, req, res, next) => {
    console.error('❌ Error:', err.stack);
    res.status(500).json({
        status: 'error',
        message: 'Something went wrong!'
    });
});

// Start server
server.listen(PORT, () => {
    console.log(`🚀 Server running on http://localhost:${PORT}`);
    console.log('📝 Environment:', process.env.NODE_ENV || 'development');
});