import { strict as assert } from "node:assert";
import { describe, it } from "node:test";
import {
  buildGeminiGenerateConfig,
  consumeGeminiContentStream,
  cumulativeTextFromParts,
  extractFunctionCallsFromParts,
  geminiIncludeThoughtsEnabled,
} from "../geminiContentStream.ts";

describe("geminiContentStream", () => {
  it("buildGeminiGenerateConfig includes thinkingConfig by default", () => {
    const prev = process.env.GEMINI_INCLUDE_THOUGHTS;
    delete process.env.GEMINI_INCLUDE_THOUGHTS;
    try {
      assert.equal(geminiIncludeThoughtsEnabled(), true);
      const cfg = buildGeminiGenerateConfig({
        systemInstruction: "sys",
        googleTools: [{ name: "write_report" }],
      });
      assert.ok(Array.isArray(cfg.tools));
      assert.ok(cfg.thinkingConfig);
      assert.equal((cfg.thinkingConfig as { includeThoughts: boolean }).includeThoughts, true);
    } finally {
      if (prev === undefined) delete process.env.GEMINI_INCLUDE_THOUGHTS;
      else process.env.GEMINI_INCLUDE_THOUGHTS = prev;
    }
  });

  it("cumulativeTextFromParts separates thought vs answer", () => {
    const { thought, text } = cumulativeTextFromParts([
      { text: "plan", thought: true },
      { text: "hi" },
      { functionCall: { name: "x" } },
    ]);
    assert.equal(thought, "plan");
    assert.equal(text, "hi");
  });

  it("extractFunctionCallsFromParts collects functionCall parts", () => {
    const calls = extractFunctionCallsFromParts([
      { text: "x" },
      { functionCall: { name: "write_report", args: { task_id: "T" } } },
    ]);
    assert.equal(calls.length, 1);
    assert.equal((calls[0] as { name: string }).name, "write_report");
  });

  it("consumeGeminiContentStream emits incremental deltas", async () => {
    async function* mockStream() {
      yield {
        candidates: [{ content: { parts: [{ text: "think", thought: true }] } }],
      };
      yield {
        candidates: [{ content: { parts: [{ text: " world", thought: true }] } }],
      };
      yield {
        candidates: [{ content: { parts: [{ text: "Hello" }] } }],
        usageMetadata: { totalTokenCount: 10 },
      };
    }

    const thinking: string[] = [];
    const assistant: string[] = [];
    const result = await consumeGeminiContentStream(mockStream(), {
      onThinkingDelta: (d) => thinking.push(d),
      onAssistantDelta: (d) => assistant.push(d),
    });

    assert.equal(thinking.join(""), "think world");
    assert.equal(assistant.join(""), "Hello");
    assert.equal(result.thinkingText, "think world");
    assert.equal(result.replyText, "Hello");
    assert.deepEqual(result.usageMetadata, { totalTokenCount: 10 });
  });
});
