/**
 * C 代码编译运行后端服务
 * 接收 C 代码 → 编译 → 运行 → 返回输出
 */
const express = require('express')
const cors = require('cors')
const { execSync } = require('child_process')
const path = require('path')
const fs = require('fs')

const app = express()
const PORT = 3001

app.use(cors())
app.use(express.json({ limit: '1mb' }))

// 查找可用的 C 编译器
// w64devkit GCC 路径
const W64DEVKIT_DIR = path.join(__dirname, 'bin', 'w64devkit', 'w64devkit')
const W64DEVKIT_GCC = path.join(W64DEVKIT_DIR, 'bin', 'gcc.exe')
const W64DEVKIT_PREFIX = path.join(W64DEVKIT_DIR, 'lib', 'gcc')

function findCompiler() {
  const candidates = [
    // MinGW / MSYS2 (PATH)
    'gcc.exe',
    'x86_64-w64-mingw32-gcc.exe',
    'i686-w64-mingw32-gcc.exe',
    // TCC (Tiny C Compiler)
    'tcc.exe',
    // Clang
    'clang.exe',
    // MSVC
    'cl.exe',
    // 本项目的便携编译器
    path.join(__dirname, 'bin', 'tcc.exe'),
    path.join(__dirname, 'bin', 'gcc.exe'),
    path.join(__dirname, '..', 'tools', 'tcc', 'tcc.exe'),
  ]

  // 先在 PATH 中查找
  for (const name of ['gcc.exe', 'tcc.exe', 'clang.exe', 'cl.exe']) {
    try {
      execSync(`where ${name}`, { stdio: 'pipe', timeout: 3000 })
      return { path: name, name }
    } catch {}
  }

  // 检查 w64devkit GCC（需设置 GCC_EXEC_PREFIX）
  if (fs.existsSync(W64DEVKIT_GCC)) {
    return { path: W64DEVKIT_GCC, name: 'gcc.exe', execPrefix: W64DEVKIT_PREFIX }
  }

  // 再检查其他具体路径
  for (const candidate of candidates) {
    try {
      const absPath = path.resolve(candidate)
      if (fs.existsSync(absPath)) {
        return { path: absPath, name: path.basename(absPath) }
      }
    } catch {}
  }

  // 搜索 Visual Studio MSVC 安装目录
  try {
    const vsPaths = [
      'C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC',
      'C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\VC\\Tools\\MSVC',
      'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC',
      'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC',
      'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC',
    ]
    for (const vsPath of vsPaths) {
      if (fs.existsSync(vsPath)) {
        const versions = fs.readdirSync(vsPath).sort().reverse()
        for (const ver of versions) {
          const clPath = path.join(vsPath, ver, 'bin', 'Hostx64', 'x64', 'cl.exe')
          if (fs.existsSync(clPath)) {
            return { path: clPath, name: 'cl.exe' }
          }
        }
      }
    }
  } catch {}

  return null
}

// 编译并运行 C 代码
app.post('/api/run-c', (req, res) => {
  const { code } = req.body
  if (!code) {
    return res.status(400).json({ error: '请提供 C 代码' })
  }

  const compiler = findCompiler()
  if (!compiler) {
    return res.status(400).json({
      error: '未找到 C 编译器',
      hint: '请安装 MinGW-w64 GCC 编译器',
      installGuide: [
        '--- 安装 MinGW-w64 ---',
        '方法一（推荐）：下载 MinGW-w64 GCC',
        '  1. 访问 https://winlibs.com/ 下载 GCC (MinGW-w64)',
        '  2. 解压并将 bin/ 目录添加到系统 PATH 环境变量',
        '  3. 重启终端后即可使用',
        '',
        '方法二（轻量）：下载 TCC (Tiny C Compiler)',
        '  将 tcc.exe 放入 server/bin/ 目录',
        '',
        '安装后重新启动: npm run server',
      ].join('\n')
    })
  }

  const tmpDir = path.join(__dirname, '..', 'tmp')
  if (!fs.existsSync(tmpDir)) {
    fs.mkdirSync(tmpDir, { recursive: true })
  }

  const srcFile = path.join(tmpDir, `code_${Date.now()}.c`)
  const outFile = path.join(tmpDir, `code_${Date.now()}.exe`)

  try {
    // 写入源码
    fs.writeFileSync(srcFile, code, 'utf-8')

    let compileCmd
    const execOptions = {
      timeout: 15000,
      cwd: tmpDir,
      encoding: 'utf-8',
      env: { ...process.env }
    }

    if (compiler.name.includes('tcc')) {
      // TCC: 编译并运行一步到位（支持 -run）
      compileCmd = `"${compiler.path}" -run "${srcFile}"`
    } else if (compiler.execPrefix) {
      // w64devkit GCC: 需要设置 GCC_EXEC_PREFIX 并加入 PATH
      const w64binDir = path.dirname(compiler.path)
      execOptions.env.GCC_EXEC_PREFIX = compiler.execPrefix + path.sep
      execOptions.env.PATH = w64binDir + path.delimiter + (execOptions.env.PATH || '')
      compileCmd = `"${compiler.path}" "${srcFile}" -o "${outFile}" -Wall -std=c99`
    } else {
      // GCC/Clang: 先编译再运行
      compileCmd = `"${compiler.path}" "${srcFile}" -o "${outFile}" -Wall -std=c99 2>&1`
    }

    // 编译
    const compileOutput = execSync(compileCmd, execOptions)

    let runOutput = compileOutput

    // GCC/Clang: 编译后还需运行 exe
    if (!compiler.name.includes('tcc') && fs.existsSync(outFile)) {
      try {
        runOutput = execSync(`"${outFile}"`, {
          timeout: 10000,
          cwd: tmpDir,
          encoding: 'utf-8',
          env: execOptions.env
        })
      } catch (runErr) {
        runOutput = runErr.stdout || runErr.message
      }
    }

    // 清理临时文件
    try {
      if (fs.existsSync(srcFile)) fs.unlinkSync(srcFile)
      if (fs.existsSync(outFile)) fs.unlinkSync(outFile)
    } catch {}

    res.json({ output: runOutput })
  } catch (compileErr) {
    // 编译错误
    res.json({
      output: compileErr.stdout || compileErr.message,
      isError: true
    })
  } finally {
    // 确保清理
    try {
      if (fs.existsSync(srcFile)) fs.unlinkSync(srcFile)
      if (fs.existsSync(outFile)) fs.unlinkSync(outFile)
    } catch {}
  }
})

// 运行 Python 代码
app.post('/api/run-py', (req, res) => {
  const { code } = req.body
  if (!code) {
    return res.status(400).json({ error: '请提供 Python 代码' })
  }

  // 查找 python3 或 python
  let pythonCmd = 'python3'
  try {
    execSync(`${pythonCmd} --version`, { stdio: 'pipe', timeout: 3000 })
  } catch {
    pythonCmd = 'python'
    try {
      execSync(`${pythonCmd} --version`, { stdio: 'pipe', timeout: 3000 })
    } catch {
      return res.status(400).json({
        error: '未找到 Python 解释器',
        hint: '请安装 Python 3 并确保在 PATH 环境变量中',
        installGuide: [
          '--- 安装 Python ---',
          '1. 访问 https://www.python.org/downloads/ 下载并安装 Python 3',
          '2. 安装时勾选 "Add Python to PATH"',
          '3. 安装后重启终端',
        ].join('\n')
      })
    }
  }

  const tmpDir = path.join(__dirname, '..', 'tmp')
  if (!fs.existsSync(tmpDir)) {
    fs.mkdirSync(tmpDir, { recursive: true })
  }

  const srcFile = path.join(tmpDir, `code_${Date.now()}.py`)

  try {
    fs.writeFileSync(srcFile, code, 'utf-8')
    const output = execSync(`"${pythonCmd}" "${srcFile}"`, {
      timeout: 15000,
      cwd: tmpDir,
      encoding: 'utf-8'
    })
    res.json({ output })
  } catch (runErr) {
    res.json({
      output: runErr.stdout || runErr.message,
      isError: true
    })
  } finally {
    try { if (fs.existsSync(srcFile)) fs.unlinkSync(srcFile) } catch {}
  }
})

// 健康检查
app.get('/api/status', (req, res) => {
  const compiler = findCompiler()
  res.json({
    status: 'ok',
    compiler: compiler ? `${compiler.name} (${compiler.path})` : '未安装'
  })
})

// 下载 TCC 脚本
app.get('/api/setup-compiler', (req, res) => {
  res.json({
    message: '请手动下载 TCC:',
    url: 'https://raw.githubusercontent.com/FooBarWidget/tinycc/master/tcc.exe',
    instructions: `将 tcc.exe 放入 ${path.join(__dirname, 'bin')} 目录`
  })
})

app.listen(PORT, () => {
  console.log(`✅ C 代码运行服务已启动: http://localhost:${PORT}`)
  const compiler = findCompiler()
  if (compiler) {
    console.log(`   检测到编译器: ${compiler.name}`)
  } else {
    console.log(`   ⚠️  未检测到 C 编译器，请安装后使用`)
    console.log(`   下载 TCC: https://raw.githubusercontent.com/FooBarWidget/tinycc/master/tcc.exe`)
    console.log(`   放置路径: ${path.join(__dirname, 'bin', 'tcc.exe')}`)
  }
})
