/**
 * Tauri stack adapter — spawns tauri-driver, TCP readiness probe,
 * routes through tauri:options capabilities.
 */

import { spawn, type ChildProcess } from 'node:child_process';
import { createConnection } from 'node:net';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { existsSync } from 'node:fs';
import { StackAdapter, type StackCapabilities } from './base-adapter.ts';
import type { TestFixture } from '../infra/fixtures.ts';

const __dirname = dirname(fileURLToPath(import.meta.url));
const PROJECT_ROOT = resolve(__dirname, '../../..');

export class TauriAdapter extends StackAdapter {
  readonly name = 'tauri';
  readonly port = 9750;

  getBinaryPath(): string {
    return resolve(PROJECT_ROOT, 'target/debug/agent-orchestrator');
  }

  getDataDir(fixture: TestFixture): string {
    return fixture.dataDir;
  }

  getCapabilities(fixture: TestFixture): StackCapabilities {
    return {
      capabilities: {
        'wdio:enforceWebDriverClassic': true,
        'tauri:options': {
          application: this.getBinaryPath(),
          env: fixture.env,
        },
      },
    };
  }

  setupDriver(): Promise<ChildProcess> {
    return new Promise((res, reject) => {
      // Check port is free first
      const preCheck = createConnection({ port: this.port, host: 'localhost' }, () => {
        preCheck.destroy();
        reject(new Error(
          `Port ${this.port} already in use. Kill: lsof -ti:${this.port} | xargs kill`
        ));
      });

      preCheck.on('error', () => {
        preCheck.destroy();
        const driver = spawn('tauri-driver', ['--port', String(this.port)], {
          stdio: ['ignore', 'pipe', 'pipe'],
        });

        driver.on('error', (err) => {
          reject(new Error(
            `Failed to start tauri-driver: ${err.message}. Install: cargo install tauri-driver`
          ));
        });

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

  teardownDriver(driver: ChildProcess): void {
    driver.kill();
  }

  verifyBinary(): void {
    if (!existsSync(this.getBinaryPath())) {
      throw new Error(
        `Tauri binary not found at ${this.getBinaryPath()}. ` +
        'Build with: npm run tauri build --debug --no-bundle'
      );
    }
  }
}
