#!/usr/bin/env npx tsx
// run an external detox test against sootsim
// usage: EXTERNAL_TEST_ROOT=/path/to/tests npx tsx test/detox-driver/run-test.ts [test-file-path]
// example: EXTERNAL_TEST_ROOT=/tmp/demo-app npx tsx test/detox-driver/run-test.ts e2e/MyFlow.test.ts
//
// the test file path is resolved relative to EXTERNAL_TEST_ROOT when provided
// the sootsim dev server must be running on port 5173

import { execSync } from 'child_process'
import * as fs from 'fs'
import * as path from 'path'
import { fileURLToPath } from 'url'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

const SOOTSIM_ROOT = path.resolve(__dirname, '../..')
const EXTERNAL_TEST_ROOT = process.env.EXTERNAL_TEST_ROOT || ''
const DRIVER_DIR = path.resolve(__dirname)

// get test file arg
const testFile = process.argv[2]
if (!testFile) {
  console.error('usage: npx tsx test/detox-driver/run-test.ts <test-file>')
  console.error(
    '  e.g. npx tsx test/detox-driver/run-test.ts e2e/PressStyleNative.test.ts',
  )
  process.exit(1)
}

// resolve the test file path
let testPath = testFile
if (!path.isAbsolute(testPath)) {
  const fromExternal = EXTERNAL_TEST_ROOT
    ? path.resolve(EXTERNAL_TEST_ROOT, testPath)
    : ''
  if (fromExternal && fs.existsSync(fromExternal)) {
    testPath = fromExternal
  } else {
    testPath = path.resolve(process.cwd(), testPath)
  }
}

if (!fs.existsSync(testPath)) {
  console.error(`test file not found: ${testPath}`)
  process.exit(1)
}

console.log(`running detox test against sootsim:`)
console.log(`  test: ${testPath}`)
console.log(`  sootsim:  ${SOOTSIM_ROOT}`)
console.log(`  external root: ${EXTERNAL_TEST_ROOT || '(none)'}`)
console.log('')

// write a temporary jest config with the right module mappings
const tmpConfig = path.join(SOOTSIM_ROOT, 'test', '.detox-sootsim-jest.config.cjs')
const configContent = `
// auto-generated jest config for running detox tests against sootsim
const path = require('path');

module.exports = {
  rootDir: ${JSON.stringify(EXTERNAL_TEST_ROOT || SOOTSIM_ROOT)},
  testMatch: [${JSON.stringify(testPath)}],
  testTimeout: 180000,
  maxWorkers: 1,
  verbose: true,
  transform: {
    '^.+\\.tsx?$': ['ts-jest', {
      isolatedModules: true,
      tsconfig: {
        module: 'commonjs',
        target: 'es2020',
        esModuleInterop: true,
        jsx: 'react-jsx',
        strict: false,
        skipLibCheck: true,
        moduleResolution: 'node',
        allowJs: true,
        resolveJsonModule: true,
      },
    }],
  },
  moduleNameMapper: {
    '^detox$': ${JSON.stringify(path.join(DRIVER_DIR, 'index.ts'))},
    '^\\\\./utils/navigation$': ${JSON.stringify(path.join(DRIVER_DIR, 'navigation.ts'))},
    '^\\\\./utils/colors$': ${JSON.stringify(path.join(DRIVER_DIR, 'colors.ts'))},
  },
  testEnvironment: 'node',
};
`

fs.writeFileSync(tmpConfig, configContent)

try {
  const cmd = `npx jest --config ${tmpConfig} --no-cache --forceExit`
  console.log(`$ ${cmd}\n`)

  execSync(cmd, {
    stdio: 'inherit',
    cwd: SOOTSIM_ROOT,
    env: {
      ...process.env,
      SOOTSIM_URL: process.env.SOOTSIM_URL || 'http://localhost:5173',
    },
  })
} catch (e: any) {
  process.exit(e.status || 1)
} finally {
  // clean up temp config
  try {
    fs.unlinkSync(tmpConfig)
  } catch {}
}
