/**
 * WebDriverIO config for Tauri stack E2E tests.
 *
 * Extends shared config with tauri-driver lifecycle and capabilities.
 * Port: 9750 (per project convention).
 */

import { spawn, execSync } from 'node:child_process';
import { createConnection } from 'node:net';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { rmSync, existsSync } from 'node:fs';
import { createTestFixture } from './infra/fixtures.ts';
import { sharedConfig } from './wdio.shared.conf.js';

const __dirname = dirname(fileURLToPath(import.meta.url));
const projectRoot = resolve(__dirname, '../..');
const tauriBinary = resolve(projectRoot, 'target/debug/agent-orchestrator');

let tauriDriver;

const fixture = createTestFixture('agor-e2e-tauri');
process.env.AGOR_TEST = '1';
process.env.AGOR_TEST_DATA_DIR = fixture.dataDir;
process.env.AGOR_TEST_CONFIG_DIR = fixture.configDir;

const TAURI_DRIVER_PORT = 9750;

console.log(`[tauri] Test fixture at ${fixture.rootDir}`);

export const config = {
  ...sharedConfig,

  port: TAURI_DRIVER_PORT,

  capabilities: [{
    'wdio:enforceWebDriverClassic': true,
    'tauri:options': {
      application: tauriBinary,
      env: fixture.env,
    },
  }],

  onPrepare() {
    // Kill stale tauri-driver on our port
    try {
      const pids = execSync(`lsof -ti:${TAURI_DRIVER_PORT} 2>/dev/null`, { encoding: 'utf8' }).trim();
      if (pids) {
        console.log(`Killing stale process(es) on port ${TAURI_DRIVER_PORT}: ${pids}`);
        execSync(`kill ${pids} 2>/dev/null`);
      }
    } catch { /* no process — good */ }

    // Verify devUrl port is free
    const DEV_URL_PORT = 9710;
    try {
      const devPids = execSync(`lsof -ti:${DEV_URL_PORT} 2>/dev/null`, { encoding: 'utf8' }).trim();
      if (devPids) {
        throw new Error(
          `Port ${DEV_URL_PORT} (Tauri devUrl) in use by PIDs: ${devPids}. ` +
          `Stop that process or use a release build.`
        );
      }
    } catch (e) {
      if (e.message.includes(`Port ${DEV_URL_PORT}`)) throw e;
    }

    if (!existsSync(tauriBinary)) {
      if (process.env.SKIP_BUILD) {
        throw new Error(`Binary not found at ${tauriBinary}. Build first or unset SKIP_BUILD.`);
      }
    }

    if (process.env.SKIP_BUILD) {
      if (!existsSync(resolve(projectRoot, 'dist/index.html'))) {
        console.log('Frontend dist/ missing — building...');
        execSync('npm run build', { cwd: projectRoot, stdio: 'inherit' });
      }
      return Promise.resolve();
    }

    return new Promise((resolveHook, reject) => {
      console.log('Building frontend...');
      try {
        execSync('npm run build', { cwd: projectRoot, stdio: 'inherit' });
      } catch (e) {
        reject(new Error(`Frontend build failed: ${e.message}`));
        return;
      }
      console.log('Building Tauri debug binary...');
      const build = spawn('cargo', ['tauri', 'build', '--debug', '--no-bundle'], {
        cwd: projectRoot,
        stdio: 'inherit',
      });
      build.on('close', (code) => code === 0 ? resolveHook() : reject(new Error(`Build failed (exit ${code})`)));
      build.on('error', reject);
    });
  },

  beforeSession() {
    return new Promise((res, reject) => {
      const preCheck = createConnection({ port: TAURI_DRIVER_PORT, host: 'localhost' }, () => {
        preCheck.destroy();
        reject(new Error(`Port ${TAURI_DRIVER_PORT} already in use.`));
      });
      preCheck.on('error', () => {
        preCheck.destroy();
        tauriDriver = spawn('tauri-driver', ['--port', String(TAURI_DRIVER_PORT)], {
          stdio: ['ignore', 'pipe', 'pipe'],
        });
        tauriDriver.on('error', (err) => {
          reject(new Error(`tauri-driver failed: ${err.message}. Install: cargo install tauri-driver`));
        });

        const deadline = Date.now() + 10_000;
        function probe() {
          if (Date.now() > deadline) { reject(new Error('tauri-driver not ready within 10s')); return; }
          const sock = createConnection({ port: TAURI_DRIVER_PORT, host: 'localhost' }, () => {
            sock.destroy();
            console.log(`tauri-driver ready on port ${TAURI_DRIVER_PORT}`);
            res();
          });
          sock.on('error', () => { sock.destroy(); setTimeout(probe, 200); });
        }
        setTimeout(probe, 300);
      });
    });
  },

  async before() {
    await browser.waitUntil(
      async () => {
        const title = await browser.getTitle();
        const hasEl = await browser.execute(
          'return document.querySelector(\'[data-testid="status-bar"]\') !== null' +
          ' || document.querySelector(".project-grid") !== null' +
          ' || document.querySelector(".settings-panel") !== null'
        );
        return hasEl || title.toLowerCase().includes('agor') || title.toLowerCase().includes('orchestrator');
      },
      { timeout: 15_000, interval: 500, timeoutMsg: 'Wrong app — not Agent Orchestrator' },
    );
    console.log('[tauri] App identity verified.');
  },

  afterSession() {
    if (tauriDriver) { tauriDriver.kill(); tauriDriver = null; }
    try { rmSync(fixture.rootDir, { recursive: true, force: true }); } catch { /* best-effort */ }
  },
};
