#!/usr/bin/env bun
/**
 * hwlab-code-agent CLI — HWLAB Code Agent 客户端
 * Skill(cli-spec)
 *
 * 通过 hwlab-code-agent 直接调 HWLAB v0.2 cloud-api 管理 agent turn：
 *   spawn  - 创建 session + 提交 prompt，立即返回 traceId
 *   poll   - 轮询等待 turn 完成
 *   result - 查询 turn 结果
 *   trace  - 查询 turn trace
 */

import path from "node:path";
import { spawn, poll, getResult, getTrace } from "./src/client.ts";
import { queryKafkaEventStream } from "../../../internal/cloud/kafka-event-bridge.ts";

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

function parseArgs(from: number): Record<string, string | undefined> {
  const args: Record<string, string | undefined> = {};
  for (let i = from; i < argv.length; i++) {
    if (argv[i].startsWith("--")) {
      const key = argv[i].slice(2);
      const val = (i + 1 < argv.length && !argv[i + 1].startsWith("--")) ? argv[i + 1] : "true";
      args[key] = val;
      if (val !== "true") i++;
    }
  }
  return args;
}

async function main() {
  switch (cmd) {
    case "spawn": {
      const args = parseArgs(1);
      await spawn(args);
      break;
    }
    case "poll": {
      const traceId = argv[1];
      if (!traceId) {
        process.stderr.write(JSON.stringify({ ok: false, error: { code: "usage", message: "poll <traceId> [--timeout N]" } }) + "\n");
        process.exit(1);
      }
      await poll(traceId, parseArgs(2));
      break;
    }
    case "result": {
      const traceId = argv[1];
      if (!traceId) {
        process.stderr.write(JSON.stringify({ ok: false, error: { code: "usage", message: "result <traceId>" } }) + "\n");
        process.exit(1);
      }
      await getResult(traceId);
      break;
    }
    case "trace": {
      const traceId = argv[1];
      if (!traceId) {
        process.stderr.write(JSON.stringify({ ok: false, error: { code: "usage", message: "trace <traceId> [--full]" } }) + "\n");
        process.exit(1);
      }
      await getTrace(traceId, parseArgs(2));
      break;
    }
    case "kafka": {
      const subcommand = argv[1] || "tail";
      if (subcommand !== "tail" && subcommand !== "query") {
        process.stderr.write(JSON.stringify({ ok: false, error: { code: "usage", message: "kafka tail [--stream hwlab|agentrun] [--trace-id TRACE_ID] [--session-id SESSION_ID] [--run-id RUN_ID] [--command-id COMMAND_ID]" } }) + "\n");
        process.exit(1);
      }
      await kafkaTail(parseArgs(2));
      break;
    }
    default:
      process.stderr.write(JSON.stringify({
        ok: false,
        usage: {
          spawn: "HWLAB_CODE_AGENT_PROVIDER_PROFILE=PROFILE bun scripts/hwlab-code-agent-cli.ts spawn --message '...' [--profile PROFILE]",
          poll:   "bun scripts/hwlab-code-agent-cli.ts poll <traceId> [--timeout 600000]",
          result: "bun scripts/hwlab-code-agent-cli.ts result <traceId>",
          trace:  "bun scripts/hwlab-code-agent-cli.ts trace <traceId> [--full]",
          kafka:  "bun tools/hwlab-code-agent kafka tail --stream hwlab --trace-id trc_... --limit 20"
        }
      }, null, 2) + "\n");
      process.exit(1);
  }
}

async function kafkaTail(args: Record<string, string | undefined>) {
  const result = await queryKafkaEventStream({
    env: process.env,
    stream: args.stream || "hwlab",
    topic: args.topic || null,
    traceId: args["trace-id"] || args.traceId || null,
    sessionId: args["session-id"] || args.sessionId || null,
    runId: args["run-id"] || args.runId || null,
    commandId: args["command-id"] || args.commandId || null,
    limit: boundedInteger(args.limit, 20, 1, 500),
    timeoutMs: boundedInteger(args["timeout-ms"] || args.timeoutMs, 5000, 250, 60000),
    fromBeginning: args["from-end"] === "true" || args.fromEnd === "true" ? false : true
  });
  process.stdout.write(JSON.stringify({
    ok: true,
    action: "hwlab-code-agent.kafka.tail",
    stream: result.stream,
    topic: result.topic,
    count: result.count,
    limit: result.limit,
    timeoutMs: result.timeoutMs,
    filters: result.filters,
    rows: result.events.map(kafkaEventRow),
    events: args.full === "true" ? result.events : undefined,
    valuesPrinted: false
  }, null, 2) + "\n");
}

function kafkaEventRow(record: any) {
  const value = record?.value && typeof record.value === "object" ? record.value : {};
  const event = value.event && typeof value.event === "object" ? value.event : {};
  const context = value.context && typeof value.context === "object" ? value.context : {};
  return clean({
    topic: record.topic,
    partition: record.partition,
    offset: record.offset,
    key: record.key,
    producedAt: text(value.producedAt),
    eventType: text(value.eventType ?? event.eventType),
    traceId: text(value.traceId ?? event.traceId),
    sessionId: text(value.sessionId ?? event.sessionId),
    runId: text(context.runId ?? event.runId ?? value.runId),
    commandId: text(context.commandId ?? event.commandId ?? value.commandId),
    label: text(event.label),
    status: text(event.status),
    sourceSeq: context.sourceSeq ?? event.sourceSeq
  });
}

function boundedInteger(value: unknown, fallback: number, min: number, max: number) {
  const parsed = Number.parseInt(String(value ?? ""), 10);
  const selected = Number.isFinite(parsed) ? parsed : fallback;
  return Math.min(max, Math.max(min, selected));
}

function text(value: unknown) {
  return String(value ?? "").trim();
}

function clean(value: Record<string, unknown>) {
  return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined && item !== "" && item !== null));
}

main().catch((e) => {
  process.stderr.write(JSON.stringify({ ok: false, error: { code: "unhandled", message: e.message } }) + "\n");
  process.exit(1);
});
