const { createServer } = require('http');
const { parse } = require('url');
const next = require('next');

// Enhanced error handling for better compatibility
process.on('uncaughtException', (err) => {
  console.error('Uncaught Exception:', err);
  // Don't exit immediately in production - allow graceful shutdown
  if (process.env.NODE_ENV === 'production') {
    console.error('Continuing despite uncaught exception...');
  } else {
    process.exit(1);
  }
});

process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection at:', promise, 'reason:', reason);
  // Log but don't exit in production for better resilience
  if (process.env.NODE_ENV !== 'production') {
    process.exit(1);
  }
});

// Check if .next directory exists
const fs = require('fs');
const path = require('path');
const nextBuildPath = path.join(process.cwd(), '.next');

if (!fs.existsSync(nextBuildPath)) {
  console.error('ERROR: .next directory not found!');
  console.error('Please run "npm run build" first to create the production build.');
  process.exit(1);
}

// Verify Next.js installation is not corrupted
try {
  const nextPackagePath = require.resolve('next/package.json');
  const nextPackage = JSON.parse(fs.readFileSync(nextPackagePath, 'utf-8'));
  console.log(`Next.js version: ${nextPackage.version}`);
} catch (err) {
  console.error('ERROR: Next.js installation appears to be corrupted!');
  console.error('Please reinstall Next.js: npm uninstall next && npm install next@16.0.3 --save');
  console.error('Then rebuild: npm run build');
  process.exit(1);
}

const dev = process.env.NODE_ENV !== 'production';
const hostname = process.env.HOSTNAME || '0.0.0.0'; // Changed to 0.0.0.0 for hosting compatibility
const port = parseInt(process.env.PORT || '3000', 10);

console.log(`Starting Next.js server...`);
console.log(`Environment: ${dev ? 'development' : 'production'}`);
console.log(`Hostname: ${hostname}`);
console.log(`Port: ${port}`);

// when using middleware `hostname` and `port` must be provided below
const app = next({ dev, hostname, port });
const handle = app.getRequestHandler();

// Request timeout configuration
const REQUEST_TIMEOUT = 30000; // 30 seconds

app.prepare()
  .then(() => {
    console.log('Next.js app prepared successfully');
    
    const server = createServer(async (req, res) => {
      // Set timeout for requests
      req.setTimeout(REQUEST_TIMEOUT, () => {
        if (!res.headersSent) {
          res.statusCode = 408;
          res.end('Request timeout');
        }
      });

      // Add security headers
      res.setHeader('X-Content-Type-Options', 'nosniff');
      res.setHeader('X-Frame-Options', 'DENY');
      res.setHeader('X-XSS-Protection', '1; mode=block');

      try {
        // Be sure to pass true as the second argument to url.parse.
        // This tells it to parse the query portion of the URL.
        const parsedUrl = parse(req.url || '/', true);
        const { pathname, query } = parsedUrl;

        if (pathname === '/a') {
          await app.render(req, res, '/a', query);
        } else if (pathname === '/b') {
          await app.render(req, res, '/b', query);
        } else {
          await handle(req, res, parsedUrl);
        }
      } catch (err) {
        console.error('Error occurred handling', req.url, err);
        if (!res.headersSent) {
          res.statusCode = 500;
          res.setHeader('Content-Type', 'text/plain');
          res.end('Internal server error');
        }
      }
    });

    // Enhanced error handling
    server.once('error', (err) => {
      console.error('Server error:', err);
      if (err.code === 'EADDRINUSE') {
        console.error(`Port ${port} is already in use`);
      } else if (err.code === 'EACCES') {
        console.error(`Permission denied: Cannot bind to port ${port}`);
      }
      // In production, try to continue if possible
      if (process.env.NODE_ENV !== 'production') {
        process.exit(1);
      }
    });

    // Graceful shutdown handling
    const gracefulShutdown = (signal) => {
      console.log(`Received ${signal}, shutting down gracefully...`);
      server.close(() => {
        console.log('Server closed');
        process.exit(0);
      });
      
      // Force shutdown after 10 seconds
      setTimeout(() => {
        console.error('Forced shutdown after timeout');
        process.exit(1);
      }, 10000);
    };

    process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
    process.on('SIGINT', () => gracefulShutdown('SIGINT'));

    server.listen(port, hostname, () => {
      console.log(`> Ready on http://${hostname}:${port}`);
      console.log(`> Server started successfully`);
    });

    // Keep process alive
    server.keepAliveTimeout = 65000; // 65 seconds
    server.headersTimeout = 66000; // 66 seconds (must be > keepAliveTimeout)
  })
  .catch((err) => {
    console.error('Failed to prepare Next.js app:', err);
    console.error('Error details:', err.stack);
    process.exit(1);
  });
