/**
 * Launches an isolated MetoYou signaling server for E2E tests.
 *
 * Creates a temporary data directory so the test server gets its own
 * fresh SQLite database. The server process inherits stdio so Playwright
 * can watch stdout for readiness and the developer can see logs.
 *
 * Cleanup: the temp directory is removed when the process exits.
 */
const { mkdtempSync, writeFileSync, mkdirSync, rmSync } = require('fs');
const { join } = require('path');
const { tmpdir } = require('os');
const { spawn } = require('child_process');

const TEST_PORT = process.env.TEST_SERVER_PORT || '3099';
const SERVER_DIR = join(__dirname, '..', '..', 'server');
const SERVER_ENTRY = join(SERVER_DIR, 'src', 'index.ts');
const SERVER_TSCONFIG = join(SERVER_DIR, 'tsconfig.json');
const TS_NODE_BIN = join(SERVER_DIR, 'node_modules', 'ts-node', 'dist', 'bin.js');

// ── Create isolated temp data directory ──────────────────────────────
const tmpDir = mkdtempSync(join(tmpdir(), 'metoyou-e2e-'));
const dataDir = join(tmpDir, 'data');
mkdirSync(dataDir, { recursive: true });

writeFileSync(
  join(dataDir, 'variables.json'),
  JSON.stringify({
    serverPort: parseInt(TEST_PORT, 10),
    serverProtocol: 'http',
    serverHost: '',
    klipyApiKey: '',
    releaseManifestUrl: '',
    linkPreview: { enabled: false, cacheTtlMinutes: 60, maxCacheSizeMb: 10 },
  })
);

console.log(`[E2E Server] Temp data dir: ${tmpDir}`);
console.log(`[E2E Server] Starting on port ${TEST_PORT}...`);

// ── Spawn the server with cwd = temp dir ─────────────────────────────
// process.cwd() is used by getRuntimeBaseDir() in the server, so data/
// (database, variables.json) will resolve to our temp directory.
// Module resolution (require/import) uses __dirname, so server source
// and node_modules are found from the real server/ directory.
const child = spawn(
  process.execPath,
  [TS_NODE_BIN, '--project', SERVER_TSCONFIG, SERVER_ENTRY],
  {
    cwd: tmpDir,
    env: {
      ...process.env,
      PORT: TEST_PORT,
      SSL: 'false',
      NODE_ENV: 'test',
      DB_SYNCHRONIZE: 'true',
    },
    stdio: 'inherit',
  }
);

let shuttingDown = false;

child.on('error', (err) => {
  console.error('[E2E Server] Failed to start:', err.message);
  cleanup();
  process.exit(1);
});

child.on('exit', (code) => {
  console.log(`[E2E Server] Exited with code ${code}`);
  cleanup();

   if (shuttingDown) {
    process.exit(0);
  }
});

// ── Cleanup on signals ───────────────────────────────────────────────
function cleanup() {
  try {
    rmSync(tmpDir, { recursive: true, force: true });
    console.log(`[E2E Server] Cleaned up temp dir: ${tmpDir}`);
  } catch {
    // already gone
  }
}

function shutdown() {
  if (shuttingDown) {
    return;
  }

  shuttingDown = true;
  child.kill('SIGTERM');

  // Give child 3s to exit, then force kill
  setTimeout(() => {
    if (child.exitCode === null) {
      child.kill('SIGKILL');
    }
  }, 3_000);
}

process.on('SIGTERM', shutdown);
process.on('SIGINT', shutdown);
process.on('exit', cleanup);
