#!/usr/bin/env node
// smoke-tui.mjs — SAEEOL TUI 스모크 테스트
// PTY 환경에서 TUI를 실행하고, 런타임 에러가 있으면 캡처
import { spawn } from "node:child_process"
import { writeFileSync, mkdirSync, existsSync } from "node:fs"
import { join } from "node:path"

const TIMEOUT_MS = 8000
const OUTDIR = join(import.meta.dirname, "..", "..", ".kilo")
const STDERR_FILE = join(OUTDIR, "tui-smoke-stderr.log")
const STDOUT_FILE = join(OUTDIR, "tui-smoke-stdout.log")

if (!existsSync(OUTDIR)) mkdirSync(OUTDIR, { recursive: true })

const args = process.argv.slice(2)
const binPath = args[0] || join(import.meta.dirname, "..", "..", "bin", "saeeol.cjs")
const command = args[1] || "tui"

console.log(`[smoke] Running: node ${binPath} ${command}`)
console.log(`[smoke] Timeout: ${TIMEOUT_MS}ms`)

const child = spawn("node", [binPath, command], {
  cwd: join(import.meta.dirname, "..", ".."),
  env: { ...process.env, FORCE_COLOR: "0", TERM: "dumb", CI: "true" },
  stdio: ["pipe", "pipe", "pipe"],
})

let stdout = ""
let stderr = ""
let killed = false

child.stdout.on("data", (d) => { stdout += d })
child.stderr.on("data", (d) => { stderr += d })

const timer = setTimeout(() => {
  killed = true
  child.kill("SIGTERM")
  // SIGTERM 후 2초 대기 후 SIGKILL
  setTimeout(() => {
    if (!child.killed) child.kill("SIGKILL")
  }, 2000)
}, TIMEOUT_MS)

const exitCode = await new Promise((resolve) => {
  child.on("exit", (code) => {
    clearTimeout(timer)
    resolve(code ?? -1)
  })
})

writeFileSync(STDERR_FILE, stderr)
writeFileSync(STDOUT_FILE, stdout)

// 결과 분석
const errors = stderr.split("\n").filter((l) =>
  /error|Error|ERROR|panic|PANIC|unhandled|Unhandled|REJECTION|rejection/i.test(l)
    && !/warn|info|debug/i.test(l.split(":")[0] || "")
)

const result = {
  exitCode,
  killed,
  timeout: TIMEOUT_MS,
  stderrLines: stderr.split("\n").length,
  stdoutLines: stdout.split("\n").length,
  errorCount: errors.length,
  errors: errors.slice(0, 20),
  files: { stderr: STDERR_FILE, stdout: STDOUT_FILE },
}

console.log("\n[smoke] Result:")
console.log(JSON.stringify(result, null, 2))

if (errors.length > 0) {
  console.error(`\n[smoke] FAIL: ${errors.length} runtime error(s) detected`)
  process.exit(1)
} else if (!killed && exitCode !== 0) {
  console.error(`\n[smoke] FAIL: TUI exited with code ${exitCode}`)
  process.exit(1)
} else {
  console.log("\n[smoke] PASS: TUI ran without runtime errors")
  process.exit(0)
}
