const { defineConfig, devices } = require('@playwright/test');
const net = require('net');

/** Find an available port starting from the preferred port. */
async function getAvailablePort(preferred = 19876) {
  for (let port = preferred; port < preferred + 100; port++) {
    const available = await new Promise(resolve => {
      const server = net.createServer();
      server.unref();
      server.on('error', () => resolve(false));
      server.listen(port, '127.0.0.1', () => {
        server.close(() => resolve(true));
      });
    });
    if (available) return port;
  }
  throw new Error('No available port found');
}

// Determine the test port at config load time.
// We use a port that won't conflict with a running Docker container on 8080.
const TEST_PORT = process.env.TEST_PORT || '19876';
const TEST_HOST = process.env.TEST_HOST || 'localhost';
const TEST_URL = process.env.TEST_URL || `http://${TEST_HOST}:${TEST_PORT}`;
process.env.CPL_FORCE_RUNTIME_REBUILD ??= 'true';

module.exports = defineConfig({
  testDir: './tests/e2e',
  globalSetup: require.resolve('./tests/e2e/global-setup.js'),
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  // E2E tests share a single server instance and exercise real browser
  // network stacks; retries absorb intermittent timing/auth flakes across
  // Chromium/Firefox/WebKit without masking genuine regressions.
  retries: 2,
  workers: 1,
  reporter: [['html', { open: 'never' }]],
  timeout: 90000,
  use: {
    baseURL: TEST_URL,
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
    actionTimeout: 20000,
    navigationTimeout: 60000,
  },

  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],

  // Run local dev server before starting the tests on a non-conflicting port
  webServer: {
    // Use the Node executable directly to avoid npm's overhead on Windows,
    // which can cause Playwright to miss the "server ready" signal.
    command: 'node -r ts-node/register/transpile-only scripts/server.ts',
    url: TEST_URL,
    reuseExistingServer: !process.env.CI,
    timeout: 600000, // 10 min: server startup includes runtime plugin compilation on first run
    env: {
      PORT: TEST_PORT,
      CPL_TEST_PUBLIC_HOST: TEST_HOST,
      CPL_TEST_MOCK_REPO_URL: 'http://127.0.0.1:8083',
      CPL_TEST_MODE: 'true',
      CPL_FORCE_RUNTIME_REBUILD: process.env.CPL_FORCE_RUNTIME_REBUILD,
      CPL_JWT_SECRET: 'test-secret',
      CPL_ADMIN_GITHUB_IDS: '42'
    }
  },
});
