const { spawn } = require('child_process');
const net = require('net');

const DEFAULT_PORT = 3000;
const MAX_PORT = 3020;

function checkPort(port) {
  return new Promise((resolve) => {
    const server = net.createServer();

    server.once('error', (err) => {
      if (err.code === 'EADDRINUSE') {
        resolve(false);
      } else {
        resolve(false);
      }
    });

    server.once('listening', () => {
      server.close();
      resolve(true);
    });

    server.listen(port, '0.0.0.0');
  });
}

async function findAvailablePort(startPort = DEFAULT_PORT) {
  for (let port = startPort; port <= MAX_PORT; port++) {
    const isAvailable = await checkPort(port);
    if (isAvailable) {
      return port;
    }
  }
  throw new Error(`No available port found between ${startPort} and ${MAX_PORT}`);
}

async function startServer() {
  try {
    const port = await findAvailablePort(DEFAULT_PORT);

    if (port !== DEFAULT_PORT) {
      console.log(`Port ${DEFAULT_PORT} is in use, using port ${port} instead`);
    } else {
      console.log(`Starting server on port ${port}`);
    }

    const args = process.argv.slice(2);
    const command = args[0] || 'next';
    const commandArgs = args.slice(1);

    const child = spawn(command, [...commandArgs, '-p', String(port), '-H', '0.0.0.0'], {
      stdio: 'inherit',
      shell: true,
      env: {
        ...process.env,
        PORT: String(port)
      }
    });

    child.on('error', (error) => {
      console.error('Failed to start server:', error);
      process.exit(1);
    });

    child.on('exit', (code) => {
      process.exit(code || 0);
    });

    process.on('SIGINT', () => {
      child.kill('SIGINT');
    });

    process.on('SIGTERM', () => {
      child.kill('SIGTERM');
    });

  } catch (error) {
    console.error('Error:', error.message);
    process.exit(1);
  }
}

startServer();
