#!/usr/bin/env node
import fs from 'node:fs'
import path from 'node:path'
import { createRequire } from 'node:module'
import { fileURLToPath } from 'node:url'

const __dirname = path.dirname(fileURLToPath(import.meta.url))
const rootDir = path.resolve(__dirname, '..')
const workerDir = path.join(rootDir, 'cf-worker')
const require = createRequire(import.meta.url)

const FIELD_MAP = {
  name: 'name',
  command: 'local_command',
  args: 'local_args_json',
  healthcheckArgs: 'local_healthcheck_args_json',
  purposeScopes: 'purpose_scopes_json',
  timeoutMs: 'timeout_ms',
  enabled: 'enabled',
  notes: 'notes',
}

export function parseEnvValue(envText, key) {
  const match = String(envText || '').match(new RegExp(`^${key}=(.*)$`, 'm'))
  return match ? match[1].trim() : ''
}

export function renderRuntimeUpdate(payload) {
  const runtimeCode = String(payload?.runtimeCode || '').trim()
  const patch = payload?.patch || {}
  const command = String(patch.command || '').trim()

  if (!runtimeCode) throw new Error('local runtime code is required')
  if (!command) throw new Error('local runtime command is required')

  const fields = {}
  for (const [inputKey, column] of Object.entries(FIELD_MAP)) {
    if (!(inputKey in patch)) continue
    const value = patch[inputKey]
    if (inputKey === 'args' || inputKey === 'healthcheckArgs' || inputKey === 'purposeScopes') {
      fields[column] = JSON.stringify(Array.isArray(value) ? value : [])
    } else if (inputKey === 'enabled') {
      fields[column] = value ? 1 : 0
    } else if (inputKey === 'timeoutMs') {
      fields[column] = Number(value) || 300000
    } else {
      fields[column] = String(value ?? '')
    }
  }

  return { runtimeCode, fields }
}

export function readRuntimePatchPayload({ envPath = path.join(workerDir, '.env'), env = process.env } = {}) {
  const raw = env.AIPROS_LOCAL_RUNTIME_PATCH
    || (fs.existsSync(envPath) ? parseEnvValue(fs.readFileSync(envPath, 'utf8'), 'AIPROS_LOCAL_RUNTIME_PATCH') : '')
  if (!raw) return null
  return JSON.parse(raw)
}

export function applyRuntimePatchToDatabase(payload, { dbPath }) {
  const { DatabaseSync } = require('node:sqlite')
  const { runtimeCode, fields } = renderRuntimeUpdate(payload)
  const db = new DatabaseSync(dbPath)
  try {
    const exists = db.prepare('SELECT 1 FROM runtime_engines WHERE code = ?').get(runtimeCode)
    if (!exists) throw new Error(`runtime engine not found: ${runtimeCode}`)

    const now = Math.floor(Date.now() / 1000)
    const entries = Object.entries(fields)
    const setSql = entries.map(([column]) => `${column} = ?`).concat(['updated_at = ?']).join(', ')
    const values = entries.map(([, value]) => value).concat([now, runtimeCode])
    db.prepare(`UPDATE runtime_engines SET ${setSql} WHERE code = ?`).run(...values)
    db.prepare('UPDATE runtime_engines SET is_active = CASE WHEN code = ? THEN 1 ELSE 0 END').run(runtimeCode)
  } finally {
    db.close()
  }
  return runtimeCode
}

if (process.argv[1] === fileURLToPath(import.meta.url)) {
  const payload = readRuntimePatchPayload()
  if (!payload) {
    console.log('未配置 AIPROS_LOCAL_RUNTIME_PATCH，跳过本地运行时同步。')
    process.exit(0)
  }
  const dbPath = process.env.DB_PATH || path.join(workerDir, 'data', 'aipro.db')
  const runtimeCode = applyRuntimePatchToDatabase(payload, { dbPath })
  console.log(`✓ 已同步本地运行时到数据库：${runtimeCode}`)
}
