#!/usr/bin/env node

import { existsSync, readFileSync } from "node:fs"
import { execFileSync } from "node:child_process"
import { join, resolve } from "node:path"

const repoRoot = resolve(import.meta.dirname, "..", "..")
const runtimeDir = process.env.QJCLAW_SMOKE_RUNTIME_DIR || join(repoRoot, "vendor", "openclaw-runtime")

let failures = 0

function check(label, condition, detail) {
  if (condition) {
    console.log(`  PASS: ${label}`)
  } else {
    console.error(`  FAIL: ${label}${detail ? ` — ${detail}` : ""}`)
    failures++
  }
}

function checkFile(label, filePath) {
  check(label, existsSync(filePath), `not found: ${filePath}`)
}

function checkExec(label, cmd, args) {
  try {
    const stdout = execFileSync(cmd, args, { encoding: "utf8" }).trim()
    check(label, true, stdout)
  } catch (e) {
    check(label, false, e.message)
  }
}

console.log(`mac-runtime-smoke: validating ${runtimeDir}`)

// 1. Manifest
const manifestPath = join(runtimeDir, "runtime-manifest.json")
checkFile("runtime-manifest.json exists", manifestPath)

let manifest = null
if (existsSync(manifestPath)) {
  try {
    manifest = JSON.parse(readFileSync(manifestPath, "utf8"))
    check("manifest platform is darwin", manifest.platform === "darwin", `got: ${manifest.platform}`)
    check("manifest arch is arm64", manifest.arch === "arm64", `got: ${manifest.arch}`)
    check("manifest bundledNodeExecutable is node/bin/node", manifest.bundledNodeExecutable === "node/bin/node", `got: ${manifest.bundledNodeExecutable}`)
    check("manifest pythonExecutable is python/bin/python3", manifest.pythonExecutable === "python/bin/python3", `got: ${manifest.pythonExecutable}`)
    check("manifest ffmpegExecutable is ffmpeg/bin/ffmpeg", manifest.ffmpegExecutable === "ffmpeg/bin/ffmpeg", `got: ${manifest.ffmpegExecutable}`)
    check("manifest ffprobeExecutable is ffmpeg/bin/ffprobe", manifest.ffprobeExecutable === "ffmpeg/bin/ffprobe", `got: ${manifest.ffprobeExecutable}`)
  } catch (e) {
    check("manifest is valid JSON", false, e.message)
  }
}

// 2. Required files
checkFile("node/bin/node", join(runtimeDir, "node", "bin", "node"))
checkFile("openclaw/index.js", join(runtimeDir, "openclaw", "index.js"))
checkFile("openclaw/package/openclaw.mjs", join(runtimeDir, "openclaw", "package", "openclaw.mjs"))
checkFile("openclaw/package/package.json", join(runtimeDir, "openclaw", "package", "package.json"))
checkFile("config/openclaw.json", join(runtimeDir, "config", "openclaw.json"))
checkFile("python/bin/python3", join(runtimeDir, "python", "bin", "python3"))
checkFile("python/python-manifest.json", join(runtimeDir, "python", "python-manifest.json"))
checkFile("python/runtime-requirements.lock.txt", join(runtimeDir, "python", "runtime-requirements.lock.txt"))
checkFile("ffmpeg/bin/ffmpeg", join(runtimeDir, "ffmpeg", "bin", "ffmpeg"))
checkFile("ffmpeg/bin/ffprobe", join(runtimeDir, "ffmpeg", "bin", "ffprobe"))
checkFile("playwright-browsers", join(runtimeDir, "playwright-browsers"))
checkFile("README.md", join(runtimeDir, "README.md"))

// 3. Executable probes
const nodeExe = join(runtimeDir, "node", "bin", "node")
const pythonExe = join(runtimeDir, "python", "bin", "python3")

if (existsSync(nodeExe)) {
  checkExec("node --version", nodeExe, ["--version"])
}

if (existsSync(pythonExe)) {
  checkExec("python3 --version", pythonExe, ["--version"])
  try {
    const stdout = execFileSync(pythonExe, ["-c", "import openpyxl, pandas, requests, fastapi, imageio_ffmpeg, qiniu; print('ok')"], {
      encoding: "utf8",
      timeout: 15000,
    }).trim()
    check("python key imports", stdout === "ok", `got: ${stdout}`)
  } catch (e) {
    check("python key imports", false, e.message?.split("\n")[0])
  }
}

// 4. Config probe
const configPath = join(runtimeDir, "config", "openclaw.json")
if (existsSync(configPath)) {
  try {
    const config = JSON.parse(readFileSync(configPath, "utf8"))
    check("config gateway.mode is local", config.gateway?.mode === "local", `got: ${config.gateway?.mode}`)
    check("config gateway.bind is loopback", config.gateway?.bind === "loopback", `got: ${config.gateway?.bind}`)
  } catch (e) {
    check("config is valid JSON", false, e.message)
  }
}

// Summary
console.log("")
if (failures === 0) {
  console.log("mac-runtime-smoke: ALL PASSED")
} else {
  console.error(`mac-runtime-smoke: ${failures} FAILURE(S)`)
  process.exit(1)
}
