/**
 * WebDriverIO config for Electrobun stack E2E tests.
 *
 * Uses CDP (Chrome DevTools Protocol) via CEF mode for reliable E2E automation.
 * Electrobun must be built/run with AGOR_CEF=1 to bundle CEF and expose
 * --remote-debugging-port=9222 (configured in electrobun.config.ts).
 *
 * Port conventions:
 *   9222 — CDP debugging port (CEF)
 *   9760 — Vite dev server (HMR)
 *   9761 — (reserved, was WebKitWebDriver)
 */

import { execSync, spawn } from 'node:child_process';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { existsSync, rmSync } from 'node:fs';
import { sharedConfig } from './wdio.shared.conf.js';
import { waitForPort } from './helpers/actions.ts';

const __dirname = dirname(fileURLToPath(import.meta.url));
const projectRoot = resolve(__dirname, '../..');
const electrobunRoot = resolve(projectRoot, 'ui-electrobun');

const CDP_PORT = 9222;

// Use the Electrobun fixture generator (different groups.json format)
let fixture;
try {
  const { createTestFixture } = await import('../../ui-electrobun/tests/e2e/fixtures.ts');
  fixture = createTestFixture('agor-ebun-cdp');
} catch {
  const { createTestFixture } = await import('./infra/fixtures.ts');
  fixture = createTestFixture('agor-ebun-cdp');
}

process.env.AGOR_TEST = '1';
process.env.AGOR_CEF = '1';
process.env.AGOR_TEST_DATA_DIR = fixture.dataDir;
process.env.AGOR_TEST_CONFIG_DIR = fixture.configDir;

let viteProcess;

console.log(`[electrobun-cdp] Test fixture at ${fixture.rootDir ?? fixture.configDir}`);

let appProcess;

export const config = {
  ...sharedConfig,

  // Use ChromeDriver to attach to existing CEF via debuggerAddress
  // ChromeDriver connects to the existing CDP port WITHOUT navigating/destroying the page
  automationProtocol: 'webdriver',

  services: [['chromedriver', { args: ['--verbose'] }]],

  capabilities: [{
    browserName: 'chrome',
    'goog:chromeOptions': {
      debuggerAddress: `localhost:${CDP_PORT}`,
    },
  }],

  async onPrepare() {
    // Find existing binary or build
    const candidates = [
      resolve(electrobunRoot, 'build/dev-linux-x64/AgentOrchestrator-dev/AgentOrchestrator-dev'),
      resolve(electrobunRoot, 'build/Agent Orchestrator'),
      resolve(electrobunRoot, 'build/AgentOrchestrator'),
    ];
    let electrobunBinary = candidates.find(p => existsSync(p));

    if (!electrobunBinary && !process.env.SKIP_BUILD) {
      console.log('[electrobun-cdp] Building with CEF...');
      try {
        execSync('npx vite build', { cwd: electrobunRoot, stdio: 'inherit' });
        execSync('npx electrobun build --env=dev', { cwd: electrobunRoot, stdio: 'inherit' });
      } catch (e) {
        console.warn('[electrobun-cdp] Build failed:', e.message);
      }
      electrobunBinary = candidates.find(p => existsSync(p));
    }

    if (!electrobunBinary) {
      // Kill any stale process on CDP port before launching
      try { execSync(`fuser -k ${CDP_PORT}/tcp 2>/dev/null || true`); } catch {}

      // Start Vite dev server first (Electrobun dev mode loads JS from it)
      console.log('[electrobun-cdp] Starting Vite dev server on port 9760...');
      viteProcess = spawn('npx', ['vite', 'dev', '--port', '9760', '--host', 'localhost'], {
        cwd: electrobunRoot,
        env: { ...process.env },
        stdio: 'pipe',
      });
      viteProcess.stdout?.on('data', (d) => {
        const msg = d.toString();
        if (msg.includes('ready') || msg.includes('Local:')) console.log(`[vite] ${msg.trim()}`);
      });
      viteProcess.stderr?.on('data', (d) => process.stderr.write(`[vite] ${d}`));

      // Wait for Vite to be ready
      const viteStart = Date.now();
      while (Date.now() - viteStart < 15000) {
        try { const r = await fetch('http://localhost:9760/'); if (r.ok) break; } catch {}
        await new Promise(r => setTimeout(r, 500));
      }
      console.log('[electrobun-cdp] Vite dev server ready.');

      // Launch Electrobun with CEF
      console.log('[electrobun-cdp] Launching via electrobun dev...');
      appProcess = spawn('npx', ['electrobun', 'dev'], {
        cwd: electrobunRoot,
        env: {
          ...process.env,
          AGOR_CEF: '1',
          AGOR_TEST: '1',
          AGOR_TEST_DATA_DIR: fixture.dataDir,
          AGOR_TEST_CONFIG_DIR: fixture.configDir,
        },
        stdio: 'pipe',
      });
    } else {
      console.log(`[electrobun-cdp] Launching binary: ${electrobunBinary}`);
      appProcess = spawn(electrobunBinary, [], {
        env: {
          ...process.env,
          AGOR_CEF: '1',
          AGOR_TEST: '1',
          AGOR_TEST_DATA_DIR: fixture.dataDir,
          AGOR_TEST_CONFIG_DIR: fixture.configDir,
        },
        stdio: 'pipe',
      });
    }

    appProcess.stdout?.on('data', (d) => process.stdout.write(`[app] ${d}`));
    appProcess.stderr?.on('data', (d) => process.stderr.write(`[app] ${d}`));
    appProcess.on('exit', (code) => console.log(`[electrobun-cdp] App exited with code ${code}`));

    // Wait for CDP port to become available
    return waitForPort(CDP_PORT, 30_000);
  },

  async before() {
    // Navigate CEF to Vite dev server (views:// protocol can't serve ES modules in CEF)
    console.log('[electrobun-cdp] Navigating to Vite dev server...');
    await browser.url('http://localhost:9760/');
    await browser.pause(3000); // Wait for Svelte to mount

    // Wait for app to render
    await browser.waitUntil(
      async () => {
        const hasEl = await browser.execute(
          'return document.querySelector(".left-sidebar") !== null' +
          ' || document.querySelector(".project-card") !== null' +
          ' || document.querySelector(".status-bar") !== null' +
          ' || document.querySelector("#app")?.children?.length > 0'
        );
        return hasEl;
      },
      { timeout: 20_000, interval: 500, timeoutMsg: 'Electrobun app did not render in 20s' },
    );
    console.log('[electrobun-cdp] App loaded.');
  },

  onComplete() {
    if (appProcess) {
      console.log('[electrobun-cdp] Stopping app...');
      appProcess.kill('SIGTERM');
      appProcess = undefined;
    }
    if (viteProcess) {
      console.log('[electrobun-cdp] Stopping Vite dev server...');
      viteProcess.kill('SIGTERM');
      viteProcess = undefined;
    }

    const cleanup = fixture.cleanup ?? (() => {
      try {
        if (fixture.rootDir) rmSync(fixture.rootDir, { recursive: true, force: true });
      } catch { /* best-effort */ }
    });
    cleanup();
  },
};
