/**
 * Shared WebDriverIO configuration — common settings for both Tauri and Electrobun.
 *
 * Stack-specific configs (wdio.tauri.conf.js, wdio.electrobun.conf.js)
 * import and extend this with their own lifecycle hooks and capabilities.
 */

import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { getResultsDb } from './infra/results-db.ts';

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

export const sharedConfig = {
  // ── Runner ──
  runner: 'local',
  maxInstances: 1,

  // ── Connection defaults (overridden per-stack) ──
  hostname: 'localhost',
  path: '/',

  // ── Specs — unified set, all shared ──
  specs: [
    resolve(projectRoot, 'tests/e2e/specs/splash.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/smoke.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/groups.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/settings.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/theme.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/terminal.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/agent.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/keyboard.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/search.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/notifications.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/files.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/comms.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/tasks.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/status-bar.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/context.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/diagnostics.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/worktree.test.ts'),
    resolve(projectRoot, 'tests/e2e/specs/llm-judged.test.ts'),
  ],

  // ── Framework ──
  framework: 'mocha',
  mochaOpts: {
    ui: 'bdd',
    timeout: 180_000,
  },

  // ── Reporter ──
  reporters: ['spec'],

  // ── Logging ──
  logLevel: 'warn',

  // ── Timeouts ──
  waitforTimeout: 10_000,
  connectionRetryTimeout: 30_000,
  connectionRetryCount: 3,

  // ── Hooks ──

  /** Smart test caching: skip tests with 3+ consecutive passes */
  beforeTest(test) {
    browser.__expectedErrors = [];

    if (process.env.FULL_RESCAN) return;

    const db = getResultsDb();
    const specFile = test.file?.replace(/.*specs\//, '') ?? '';
    if (db.shouldSkip(specFile, test.title)) {
      const stats = db.getCacheStats();
      console.log(`Skipping (3+ consecutive passes): ${test.title} [${stats.skippable}/${stats.total} skippable]`);
      test.pending = true;
    }
  },

  /** After each test: check for error toasts, record in pass cache */
  async afterTest(test, _context, { passed }) {
    let unexpected = [];
    try {
      // Use string script for cross-protocol compatibility (devtools + webdriver)
      const errors = await browser.execute(
        'return (function() {' +
        '  var toasts = Array.from(document.querySelectorAll(".toast-error, .load-error"));' +
        '  return toasts.map(function(t) { return (t.textContent || "").trim(); }).filter(Boolean);' +
        '})()'
      );

      const expected = browser.__expectedErrors || [];
      unexpected = errors.filter(e => !expected.some(exp => e.includes(exp)));

      if (unexpected.length > 0 && passed) {
        throw new Error(
          `Unexpected error toast(s) during "${test.title}": ${unexpected.join('; ')}`
        );
      }
    } catch (e) {
      if (e.message?.includes('Unexpected error toast')) throw e;
    }

    const db = getResultsDb();
    const specFile = test.file?.replace(/.*specs\//, '') ?? '';
    db.recordTestResult(specFile, test.title, passed && unexpected.length === 0);
  },

  // ── TypeScript ──
  autoCompileOpts: {
    tsNodeOpts: {
      project: resolve(projectRoot, 'tests/e2e/tsconfig.json'),
    },
  },
};
