#!/usr/bin/env node

/**
 * @aineos/cli — AINEOS Command Line Interface
 *
 * Usage:
 *   aineos list [--json] [--type <type>] [--workspace <name>]
 *   aineos read <path>
 *   aineos write <path> [content]
 *   aineos diff <path> [compare]
 *   aineos init [dir]
 *   aineos config [get|set|list] [key] [value]
 *   aineos check [--rules <list>] [--fix] [--format text|json]
 *   aineos audit <query|stats|history|recent> [path] [options]
 *   aineos status
 *   aineos propagate <path> [--deep] [--format text|json]
 *   aineos create <type> <name> [--title] [--desc] [--list]
 *   aineos predict [<path>] [--risk-threshold <num>] [--list-risks]
 *   aineos --version
 *   aineos --help
 */

const { Command } = require("commander");
const pkg = require("../package.json");

const program = new Command();

program
  .name("aineos")
  .description("AINEOS Truth Store CLI — manage engineering artifacts")
  .version(pkg.version, "-v, --version")
  .option("--json", "output in JSON format")
  .option("-w, --workspace <name>", "target workspace/project name")
  .option("--cloud", "use Cloud API for heavy computations (check/heal/predict/pipeline)")
  .option("--cloud-url <url>", "Cloud API base URL (default: http://localhost:3500)")
  .option("--api-key <key>", "Cloud API Key (or set AINEOS_API_KEY env var)");

// --- list ---
program
  .command("list")
  .description("list artifacts in the Truth Store")
  .option("--type <type>", "filter by artifact type (BRD, API-SPEC, SCHEMA, ...)")
  .option("--status <status>", "filter by status")
  .action((opts) => {
    require("../commands/list")({ ...opts, json: program.opts().json, workspace: program.opts().workspace });
  });

// --- read ---
program
  .command("read")
  .description("read an artifact from the Truth Store")
  .argument("<path>", "artifact path (e.g. BRD/example-brd.json)")
  .action((path, opts) => {
    require("../commands/read")({ path, ...opts, json: program.opts().json, workspace: program.opts().workspace });
  });

// --- write ---
program
  .command("write")
  .description("write an artifact to the Truth Store")
  .argument("<path>", "artifact path (e.g. BRD/new-brd.json)")
  .argument("[content]", "content as JSON string, or --stdin to read from stdin")
  .option("--stdin", "read content from stdin")
  .action((path, content, opts) => {
    require("../commands/write")({ path, content, ...opts, json: program.opts().json, workspace: program.opts().workspace });
  });

// --- diff ---
program
  .command("diff")
  .description("compare two versions of an artifact")
  .argument("<path>", "artifact path to diff")
  .argument("[compare]", "second artifact path to compare against")
  .action((path, compare, opts) => {
    require("../commands/diff")({ path, compare, ...opts, json: program.opts().json, workspace: program.opts().workspace });
  });

// --- init ---
program
  .command("init")
  .description("initialize a new AINEOS project")
  .argument("[dir]", "project directory (default: current directory)", ".")
  .option("--force", "overwrite existing files")
  .option("--template <name>", "seed with a starter template: crud-api, auth-flow, microservice")
  .option("--list-templates", "list available starter templates")
  .action((dir, opts) => {
    require("../commands/init")({ dir, ...opts });
  });

// --- config ---
program
  .command("config")
  .description("manage AINEOS configuration")
  .argument("[action]", "get, set, list", "list")
  .argument("[key]", "config key")
  .argument("[value]", "config value")
  .action((action, key, value) => {
    require("../commands/config")({ action, key, value, json: program.opts().json });
  });

// --- check ---
program
  .command("check")
  .description("run consistency checks across artifacts")
  .option("--rules <rules>", "comma-separated rule IDs (e.g. CONS-001,CONS-002)")
  .option("--fix", "auto-fix where possible")
  .option("--format <format>", "output format: text, json", "text")
  .option("-o, --output <file>", "save report to file")
  .option("--judge", "run LLM-as-Judge parallel check (requires OPENAI_API_KEY)")
  .option("--judge-mock", "run LLM-as-Judge in mock mode (no API key)")
  .option("--judge-rules <rules>", "LLM judge rule IDs (e.g. LLM-001,LLM-002)")
  .action((opts) => {
    const globals = program.opts();
    require("../commands/check")({ ...opts, cloud: globals.cloud, cloudUrl: globals.cloudUrl, apiKey: globals.apiKey });
  });

// --- audit ---
program
  .command("audit")
  .description("query audit logs and view change history")
  .argument("[subcommand]", "query, stats, history, recent", "recent")
  .argument("[path]", "artifact path (for history subcommand)")
  .option("--userId <id>", "filter by user")
  .option("--action <action>", "filter by action (read, write, diff)")
  .option("--resource <path>", "filter by artifact path")
  .option("--limit <n>", "limit results", parseInt)
  .action((subcommand, path, opts) => {
    require("../commands/audit")({ subcommand, path, ...opts, json: program.opts().json });
  });

// --- status ---
program
  .command("status")
  .description("show system health overview and recent activity")
  .action(() => {
    require("../commands/status")({ json: program.opts().json, workspace: program.opts().workspace });
  });

// --- propagate ---
program
  .command("propagate")
  .description("analyze impact of a changed artifact (consistency propagation)")
  .argument("<path>", "artifact path that was changed")
  .option("--format <format>", "output format: text, json", "text")
  .option("--deep", "follow full cascade chain (BRD->API->SCHEMA)")
  .action((path, opts) => {
    require("../commands/propagate")({ path, ...opts, json: program.opts().json, workspace: program.opts().workspace });
  });

// --- verify ---
program
  .command("verify")
  .description("run UI-SPEC quantitative verification (completeness, design bidirectional, test generation)")
  .argument("[subcommand]", "ui-spec, design, tests, report", "report")
  .argument("[path]", "specific artifact path to verify")
  .option("--format <format>", "output format: text, json", "text")
  .option("-o, --output <file>", "save report to file")
  .option("--dry-run", "preview test generation without writing files")
  .action((subcommand, path, opts) => {
    require("../commands/verify")({ subcommand, path, ...opts, json: program.opts().json, workspace: program.opts().workspace });
  });

// --- create ---
program
  .command("create")
  .description("create a new artifact from a template")
  .argument("[type]", "artifact type (BRD, API-SPEC, SCHEMA, DESIGN, UI-SPEC, TEST-PLAN, ...)")
  .argument("[name]", "artifact name (used for ID, file name, and default title)")
  .option("--list", "list available template types")
  .option("--title <title>", "artifact title")
  .option("--desc <description>", "artifact description")
  .option("--author <author>", "author name (for DOCUMENT type)")
  .option("--resource <name>", "resource name (for API-SPEC type)")
  .option("--resource-cn <name>", "resource Chinese name (for API-SPEC type)")
  .action((type, name, opts) => {
    require("../commands/create")({ type, name, ...opts });
  });

// --- predict ---
program
  .command("predict")
  .description("predict artifact risk scores and get proactive consistency recommendations")
  .argument("[path]", "specific artifact path to analyze")
  .option("--risk-threshold <number>", "minimum risk score (0-100) to include", parseInt)
  .option("--list-risks", "show compact risk score view")
  .option("--watch", "continuous monitoring mode (refresh every N seconds)")
  .option("--watch-interval <seconds>", "watch mode refresh interval in seconds", parseInt, 30)
  .option("--format <format>", "output format: text, json", "text")
  .option("-o, --output <file>", "save report to file")
  .action((path, opts) => {
    const globals = program.opts();
    require("../commands/predict")({ path, ...opts, cloud: globals.cloud, cloudUrl: globals.cloudUrl, apiKey: globals.apiKey });
  });

// --- heal ---
program
  .command("heal")
  .description("auto-fix consistency issues (Self-Healing Engine)")
  .option("--dry-run", "preview fixes without applying (default)")
  .option("--apply", "apply fixes")
  .option("--mode <mode>", "fix confidence mode: auto, review, suggestion", "auto")
  .option("--rules <rules>", "comma-separated rule IDs (e.g. CONS-002,CONS-003)")
  .option("--no-propagate", "skip cascade impact analysis after heal")
  .option("--no-audit", "skip audit logging")
  .option("--format <format>", "output format: text, json, diff", "text")
  .option("-o, --output <file>", "save report to file")
  .action((opts) => {
    const globals = program.opts();
    require("../commands/heal")({ ...opts, cloud: globals.cloud, cloudUrl: globals.cloudUrl, apiKey: globals.apiKey });
  });

// --- preview ---
program
  .command("preview")
  .description("show change impact preview for an artifact")
  .argument("<path>", "artifact path (e.g. BRD/example-brd.json)")
  .option("--format <format>", "output format: text, json", "text")
  .action((path, opts) => {
    require("../commands/preview")({ path, ...opts, json: program.opts().json });
  });

// --- notify ---
program
  .command("notify")
  .description("manage notification channel binding and configuration")
  .argument("[subcommand]", "list, setup, ui, test, remove", "list")
  .argument("[channel]", "channel id (wechat, dingtalk, slack)")
  .option("--webhook <url>", "webhook URL (for setup subcommand)")
  .option("--name <name>", "channel display name")
  .option("--port <port>", "Web UI port", parseInt)
  .action(async (subcommand, channel, opts) => {
    await require("../commands/notify")({ subcommand, channel, ...opts });
  });

// --- run ---
program
  .command("run")
  .description("execute function-based skills and pipelines")
  .argument("[subcommand]", "skill-id, list, info, pipeline", "list")
  .argument("[name]", "pipeline name or skill name")
  .option("--category <category>", "filter by category (function, governance)")
  .option("--rules <rules>", "comma-separated rule IDs")
  .option("--path <path>", "artifact path")
  .option("--type <type>", "artifact type filter")
  .option("--content <content>", "content for write operations")
  .option("--limit <n>", "history limit (for history subcommand)", parseInt)
  .action((subcommand, name, opts) => {
    const globals = program.opts();
    require("../commands/run")({ subcommand, skill: subcommand, name, ...opts, json: globals.json, cloud: globals.cloud, cloudUrl: globals.cloudUrl, apiKey: globals.apiKey });
  });

// --- demo ---
program
  .command("demo")
  .description("5-minute end-to-end demo: BRD → API → Schema → Check → Web UI")
  .option("--port <port>", "Web UI port (for step 6)", parseInt)
  .option("--skip-ui", "skip the Web UI step")
  .action(async (opts) => {
    await require("../commands/demo")(opts);
  });

// --- auto ---
program
  .command("auto")
  .description("autonomous consistency cycle: check → predict → heal → propagate → audit")
  .option("--dry-run", "preview fixes without applying (default)")
  .option("--apply", "apply fixes")
  .option("--mode <mode>", "heal confidence mode: auto, review, suggestion", "auto")
  .option("--risk-threshold <n>", "minimum risk score (0-100) to include", parseInt)
  .option("--watch <s>", "continuous monitoring interval in seconds", parseInt)
  .option("--no-propagate", "skip cascade impact analysis")
  .option("--no-audit", "skip audit logging")
  .option("--deep", "deep cascade propagation (BRD→API→SCHEMA)")
  .option("--format <format>", "output format: text, json", "text")
  .option("-o, --output <file>", "save report to file")
  .action((opts) => {
    const globals = program.opts();
    require("../commands/auto")({ ...opts, cloud: globals.cloud, cloudUrl: globals.cloudUrl, apiKey: globals.apiKey });
  });

// --- hooks ---
program
  .command("hooks")
  .description("manage git hooks for AINEOS consistency checks")
  .argument("[action]", "install, uninstall, status", "status")
  .action((action) => {
    const { findProjectRoot } = require("../lib/utils");
    const { installPreCommit, uninstallPreCommit } = require("../lib/git-hooks");
    const projectDir = findProjectRoot(process.cwd());
    if (!projectDir) {
      console.error("错误: 不在 AINEOS 项目中");
      process.exit(1);
    }
    switch (action) {
      case "install":
        const result = installPreCommit(projectDir);
        console.log(`  ${result.success ? "✅" : "⚠️"} ${result.message}`);
        break;
      case "uninstall":
        const uResult = uninstallPreCommit(projectDir);
        console.log(`  ${uResult.success ? "✅" : "⚠️"} ${uResult.message}`);
        break;
      default:
        const hookPath = require("path").join(projectDir, ".git", "hooks", "pre-commit");
        const exists = require("fs").existsSync(hookPath);
        if (exists) {
          const content = require("fs").readFileSync(hookPath, "utf-8");
          const isAineos = content.includes("AINEOS");
          console.log(`  pre-commit hook: ${isAineos ? "✅ AINEOS" : "⚠️ 第三方"} 已安装`);
        } else {
          console.log("  pre-commit hook: 未安装");
        }
        console.log(`  安装:   aineos hooks install`);
        console.log(`  卸载:   aineos hooks uninstall`);
    }
  });

// --- workspace ---
program
  .command("workspace")
  .description("管理多项目工作区 (workspace): init, list, switch, info")
  .argument("[subcommand]", "init, list, switch, info", "list")
  .argument("[name]", "workspace 名称")
  .option("--force", "覆盖已存在的 workspace（用于 init）")
  .option("--template <name>", "从模板初始化（用于 init）")
  .action((subcommand, name, opts) => {
    require("../commands/workspace")({ subcommand, name, ...opts });
  });

// --- sync ---
program
  .command("sync")
  .description("sync Truth Store with Cloud API")
  .argument("[subcommand]", "操作: status, push, pull, resolve", "status")
  .argument("[path]", "artifact path (for resolve)")
  .option("--dry-run", "预览变更，不实际执行")
  .option("--force", "强制覆盖冲突")
  .option("--path <path>", "仅同步指定路径的资产")
  .option("--strategy <strategy>", "冲突解决策略: keep-local, keep-remote")
  .option("--since <date>", "仅拉取指定日期之后的变更")
  .action((subcommand, pathArg, opts) => {
    const globals = program.opts();
    require("../commands/sync")({
      subcommand,
      path: opts.path || pathArg,
      ...opts,
      apiKey: globals.apiKey,
      cloudUrl: globals.cloudUrl,
    });
  });

// --- license ---
program
  .command("license")
  .description("管理 AINEOS License")
  .argument("[action]", "操作: status, activate, deactivate", "status")
  .argument("[key]", "License Key（activate 时必需）")
  .action((action, key) => {
    require("../commands/license")(action, key);
  });

// --- templates ---
program
  .command("templates")
  .description("模板市场: 搜索、查看、安装项目模板")
  .argument("[subcommand]", "操作: list, search, info, install", "list")
  .argument("[arg]", "搜索关键词 或 模板 ID（search/info/install 时需要）")
  .action((subcommand, arg) => {
    require("../commands/templates")(subcommand, arg);
  });

// --- completion ---
program
  .command("completion")
  .description("generate shell completion scripts")
  .argument("[shell]", "shell type: bash, zsh", "bash")
  .action((shell) => {
    const fs = require("fs");
    const path = require("path");
    const completionDir = path.resolve(__dirname, "../completions");
    const file = shell === "zsh" ? "_aineos" : "aineos";
    const completionPath = path.join(completionDir, shell, file);
    if (fs.existsSync(completionPath)) {
      process.stdout.write(fs.readFileSync(completionPath, "utf-8"));
    } else {
      console.error(`Unsupported shell: ${shell}. Available: bash, zsh`);
      process.exit(1);
    }
  });

// Global error handler for uncaught exceptions
process.on("uncaughtException", (err) => {
  const { formatError } = require("../lib/errors");
  process.stderr.write(formatError(err));
  process.exit(1);
});

program.parse(process.argv);
