#!/usr/bin/env node

import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { readFileSync } from 'node:fs'
import { CacheManager } from '../src/cache/index.js'
import { checkNodeVersion } from '../src/runtime/node-version.js'
import { resolveRunContext } from '../src/runtime/locate.js'

const __dirname = path.dirname(fileURLToPath(import.meta.url))

// 版本门槛先行（M0 起的不变量；纯比较在 node-version.js，副作用留这里）
const gate = checkNodeVersion(process.version)
if (!gate.ok) {
  console.error(gate.message)
  process.exit(1)
}

const argv = process.argv.slice(2)
const command = argv[0]

if (command === '--version' || command === '-v') {
  const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
  console.log(pkg.version)
  process.exit(0)
}

if (!command || command === '--help') {
  console.log('用法：webnovel-writer <命令> [选项]')
  console.log('')
  console.log('精准读取接口（逐条清单如下）：')
  console.log('  read-chapter <章号> [--front-matter|--tail=N|--head=N|--摘要]')
  console.log('  read-chapters [--range=a-b --摘要|--recent=N --tail=M]')
  console.log('  list-chapters --章定位=推进 [--卷=N]')
  console.log('  read-thread <ID> [--履历|--收尾计划|--描述]')
  console.log('  list-threads [--悬了太久|--type=<t> [--status=<s>]|--strength=<强>]')
  console.log('  read-timeline [--current-and-prev|--current-volume|--卷=N|--在场=名]')
  console.log('  read-character <正名> [--front-matter|--section=<标题>]')
  console.log('  resolve-alias <别名>')
  console.log('  list-characters [--status=<状态>]')
  console.log('  read-worldview --section=<标题>')
  console.log('  read-secret <ID> [--基本信息|--内容]')
  console.log('  list-secrets [--reader-knows=false]')
  console.log('  read-outline [--总纲 [--section=<标题>|--结局]|--卷=N [--section=<标题>]]')
  console.log('  list-volumes')
  console.log('  grep-story <关键词> [--regex=<pattern>]')
  console.log('  report-overdue-threads | report-secret-accumulation | report-thread-activity --卷=N')
  console.log('  report-weak-hook-streak | report-book-stats | report-style-drift')
  console.log('')
  console.log('写章流程（M2，零 AI 脚本面）：')
  console.log('  prepare-chapter <章号>                  备料：写出 工作区/本章写作材料.md')
  console.log('  mechanical-check <章号> [--draft=<路径>]  机检：字数/禁词/禁句式/复读/新专名/信息差候选')
  console.log('')
  console.log('宿主通道（M5，AI 产物经文件回流；JSON 一律 --file/--payload 文件路径）：')
  console.log('  review-input <章号> [--draft=<路径>]      组装两审输入 → 工作区/审稿输入.json')
  console.log('  save-review <章号> --file=<两审json>      两审报告校验合并 → 工作区/审稿.md')
  console.log('  persist-outline --file=<json>            细纲落盘（{细纲}）')
  console.log('  persist-book --file=<json> [--dir=<目录>] 建书落盘+登记（{book,总纲,卷纲}）')
  console.log('  persist-volume-review --file=<json>      卷复盘落盘（{卷号,卷摘要,下卷卷纲,伏笔条目}）')
  console.log('  persist-repair --file=<json>             修复回写（{repairs}，仅限检测失败清单内）')
  console.log('  finalize <章号> --payload=<json>          定稿原子 commit + 缓存刷新')
  console.log('')
  console.log('安装与多本书（M5）：')
  console.log('  init [--hosts=a,b] [--force]             装出工作目录（AGENTS.md/.webnovel/平台壳）')
  console.log('  update [--hosts=a,b] [--force]           升级：哈希未变更新，手改跳过并列出')
  console.log('  list-books                               书单（登记缺失自动扫描重建）')
  console.log('  switch-book <书名>                       换书：改「当前」标记')
  console.log('  session-context                          会话上下文注入文本（hook 与入口同源）')
  console.log('  migrate <v6项目路径> [--dir=<目录名>]     v6 书项目一次性迁移成 v7 书仓库（源只读，报告落工作区）')
  console.log('')
  console.log('状态机 / 例外流程（M3）：')
  console.log('  next [--json]                           继续：状态机判定下一步（--json 出完整 DTO）')
  console.log('  health-check                            体检：账面 + 高频意象/句式/指纹漂移/缺时间锚点，报告落工作区')
  console.log('  impact <关键词>                          影响分析：哪些章建立在这个事实上（已发布/未发布）')
  console.log('  goto-chapter <章号> [--confirm]          回到第N章（先备份再回滚，作者不碰 git）')
  console.log('  relink --message=<一句话说明>            补登手改：定稿/大纲 未登记改动入档（fix(手改)）')
  console.log('  export <章号> | --range=a-b | --all      干净导出：去 front matter 纯正文 → 工作区/导出/')
  console.log('')
  console.log('自动模式（M6，连写按批次定稿）：')
  console.log('  stage-chapter <章号> --payload=<json>    暂存一章进待定稿批次（不 commit），返回停止判定')
  console.log('  batch-status [--json]                   批次全貌：各章状态/审稿摘要/停止条件')
  console.log('  finalize-batch [--until=<章号>]          作者敲定后逐章按序原子定稿（每章独立 commit）')
  console.log('  batch-reject <章号>                      打回第K章，其后各章标记受影响待重审')
  console.log('  batch-restage <章号>                     受影响章重审完成，收回待审收')
  console.log('  batch-discard                           整批丢弃（未入档，定稿零变化；先经作者确认）')
  process.exit(0)
}

// 解析选项与位置参数：--key=value → {key:value}，--flag → {flag:true}
function parseArgs(rest) {
  const options = {}
  const positionalArgs = []
  for (const arg of rest) {
    if (arg.startsWith('--')) {
      const m = arg.match(/^--([^=]+)(?:=(.*))?$/)
      if (m) options[m[1]] = m[2] !== undefined ? m[2] : true
    } else {
      positionalArgs.push(arg)
    }
  }
  return { options, positionalArgs }
}

// 命令名白名单（G-9）：命令即 commands/ 下的文件名，路径拼接 import 不给 `../` 之类
// 输入把报错降级成「mod.run is not a function」——不匹配直接走「未知命令」
if (!/^[a-z0-9-]+$/.test(command)) {
  console.error(`未知命令「${command}」。运行 webnovel-writer --help 查看可用命令。`)
  process.exit(1)
}

let cache
try {
  const commandPath = path.join(__dirname, '../src/commands', `${command}.js`)
  const commandUrl = new URL(`file:///${commandPath.replace(/\\/g, '/')}`).href
  const mod = await import(commandUrl)

  const { options, positionalArgs } = parseArgs(argv.slice(1))
  const packageRoot = path.join(__dirname, '..')

  // 工作目录定位（story-repo-spec §2.0）：书仓库直启 / 工作目录当前书 / 人话提示
  const plan = await resolveRunContext(process.cwd(), { scope: mod.scope || 'book' })

  if (plan.mode === 'error' || (plan.mode === 'workdir-no-book' && !mod.allowNoBook)) {
    console.error(plan.message)
    process.exitCode = 1
  } else {
    let ctx
    if (plan.mode === 'workdir') {
      ctx = { workdir: plan.workdir, packageRoot }
    } else if (plan.mode === 'workdir-no-book') {
      // 空工作目录里允许跑的命令（next → 状态机报序1 建书引导）
      ctx = { workdir: plan.workdir, packageRoot, repoPath: null, cache: null }
    } else {
      cache = new CacheManager(path.join(plan.repoPath, '.cache', 'index.db'))
      await cache.ensureReady(plan.repoPath)
      ctx = { repoPath: plan.repoPath, cache, workdir: plan.workdir ?? null, packageRoot }
    }

    const result = await mod.run(positionalArgs, options, ctx)
    if (result.ok) {
      if (result.output) console.log(result.output)
      process.exitCode = 0
    } else {
      console.error(result.error)
      process.exitCode = 1
    }
  }
} catch (err) {
  if (err.code === 'ERR_MODULE_NOT_FOUND' || err.code === 'ENOENT') {
    console.error(`未知命令「${command}」。运行 webnovel-writer --help 查看可用命令。`)
    process.exitCode = 1
  } else {
    // 永不带栈崩溃（错误规范 §1）
    console.error(`执行命令「${command}」时出错：${err.message}`)
    process.exitCode = 1
  }
} finally {
  if (cache) await cache.close() // 显式关闭，避免 Windows 文件锁
}
