/**
 * ClaudeCodeRunHandle — parse, tool-count inference, and settle semantics (§14.4).
 */

import assert from "node:assert/strict";
import { test } from "node:test";

import {
  ClaudeCodeRunHandle,
  inferToolCallsCount,
  parseClaudeStdout,
} from "../ClaudeCodeRunHandle.ts";

test("parseClaudeStdout: single JSON object", () => {
  const parsed = parseClaudeStdout(
    JSON.stringify({ result: "hello", is_error: false, usage: { tool_calls: 2 } }),
  );
  assert.ok(parsed);
  assert.equal(parsed.result, "hello");
  assert.equal(parsed.is_error, false);
});

test("parseClaudeStdout: trailing NDJSON result line", () => {
  const stdout = [
    JSON.stringify({ type: "assistant", message: "working" }),
    JSON.stringify({ type: "result", result: "done", is_error: false }),
  ].join("\n");
  const parsed = parseClaudeStdout(stdout);
  assert.ok(parsed);
  assert.equal(parsed.result, "done");
});

test("inferToolCallsCount: success with usage.tool_calls", () => {
  const parsed = parseClaudeStdout(
    JSON.stringify({ result: "ok", usage: { tool_calls: 3 } }),
  );
  assert.equal(inferToolCallsCount(parsed, false), 3);
});

test("inferToolCallsCount: failure without parseable usage returns -1", () => {
  assert.equal(inferToolCallsCount(null, true), -1);
  const parsed = parseClaudeStdout(JSON.stringify({ result: "err", is_error: true }));
  assert.equal(inferToolCallsCount(parsed, true), -1);
});

test("ClaudeCodeRunHandle: success settles finished with tool count", async () => {
  const handle = new ClaudeCodeRunHandle({
    sessionId: "sess-1",
    agentId: "DEV-01",
    runId: "run-test-1",
  });

  handle._finalizeFromOutputForTest(
    JSON.stringify({
      result: "Task complete",
      is_error: false,
      usage: { tool_calls: 4 },
    }),
    "",
    0,
  );

  const run = await handle.whenSettled();
  assert.equal(run.status, "finished");
  assert.equal(run.tool_calls_count, 4);
  assert.equal(run.failure_code, undefined);
  assert.equal(handle.isActive(), false);
});

test("ClaudeCodeRunHandle: JSON parse failure uses tool_calls_count -1", async () => {
  const handle = new ClaudeCodeRunHandle({
    sessionId: "sess-2",
    agentId: "DEV-01",
    runId: "run-test-2",
  });

  handle._finalizeFromOutputForTest("not-json-at-all", "stderr hint", 1);

  const run = await handle.whenSettled();
  assert.equal(run.status, "failed");
  assert.equal(run.tool_calls_count, -1);
  assert.equal(run.failure_code, "CLAUDE_JSON_PARSE_FAILED");
});

test("ClaudeCodeRunHandle: empty stdout fails with CLAUDE_EMPTY_OUTPUT", async () => {
  const handle = new ClaudeCodeRunHandle({
    sessionId: "sess-3",
    agentId: "DEV-01",
    runId: "run-test-3",
  });

  handle._finalizeFromOutputForTest("", "", 1);

  const run = await handle.whenSettled();
  assert.equal(run.status, "failed");
  assert.equal(run.failure_code, "CLAUDE_EMPTY_OUTPUT");
  assert.equal(run.tool_calls_count, -1);
});
