import { beforeEach, describe, expect, it } from "vitest";

import { ChatSessionMode, ChatTurnStatus } from "@gadget/api";
import { AgentService, type IAgentWorkOrder } from "./agent.ts";

describe("AgentService", () => {
  let service: AgentService;

  beforeEach(async () => {
    service = new AgentService();
    await service.start();
  });

  it("replays historical tool results as role:tool messages with unaltered content", () => {
    const user = {
      _id: "user-1",
      email: "user@example.com",
      email_lc: "user@example.com",
      displayName: "User",
      flags: {
        isEmailVerified: true,
        isAdmin: false,
        isTest: true,
        isBanned: false,
      },
    };
    const session = {
      _id: "session-1",
      createdAt: new Date(),
      user,
      project: "project-1",
      name: "Test Session",
      mode: ChatSessionMode.Build,
      provider: "provider-1",
      selectedModel: "model",
      stats: {
        turnCount: 0,
        toolCallCount: 0,
        inputTokens: 0,
        outputTokens: 0,
      },
      pins: [],
    };
    const workOrder: IAgentWorkOrder = {
      createdAt: new Date(),
      turn: {
        _id: "turn-current",
        createdAt: new Date(),
        user,
        project: "project-1",
        session,
        provider: "provider-1",
        llm: "model",
        mode: ChatSessionMode.Build,
        status: ChatTurnStatus.Processing,
        prompts: { user: "continue" },
        blocks: [],
        toolCalls: [],
        subagents: [],
        stats: {
          toolCallCount: 0,
          inputTokens: 0,
          thinkingTokenCount: 0,
          responseTokens: 0,
          durationMs: 0,
          durationLabel: "pending",
        },
      },
      context: [
        {
          _id: "turn-1",
          createdAt: new Date(),
          user,
          project: "project-1",
          session,
          provider: "provider-1",
          llm: "model",
          mode: ChatSessionMode.Build,
          status: ChatTurnStatus.Finished,
          prompts: { user: "Read index.html" },
          blocks: [
            {
              mode: "responding",
              createdAt: new Date(),
              content: "I read the file.",
            },
          ],
          toolCalls: [
            {
              callId: "call-1",
              name: "file_read",
              parameters: '{"path":"index.html"}',
              response: "PATH: index.html\n---\ncontent",
            },
          ],
          subagents: [],
          stats: {
            toolCallCount: 1,
            inputTokens: 0,
            thinkingTokenCount: 0,
            responseTokens: 0,
            durationMs: 0,
            durationLabel: "done",
          },
        },
      ],
    };

    const messages = service.buildSessionContext(workOrder);

    expect(messages.map((message) => message.role)).toEqual([
      "user",
      "assistant",
      "tool",
    ]);
    expect(messages[1]?.toolCalls).toBeDefined();
    expect(messages[1]?.toolCalls).toHaveLength(1);
    expect(messages[1]?.toolCalls?.[0]?.id).toBe("call-1");
    expect(messages[1]?.toolCalls?.[0]?.function?.name).toBe("file_read");
    expect(messages[2]?.role).toBe("tool");
    expect(messages[2]?.content).toBe("PATH: index.html\n---\ncontent");
    expect(messages[2]?.toolCallId).toBe("call-1");
  });

  it("does not expose mutating file tools in plan mode", () => {
    const toolNames = service.getToolNamesForMode(ChatSessionMode.Plan);

    expect(toolNames).toContain("file_read");
    expect(toolNames).toContain("fetch_url");
    expect(toolNames).toContain("search_google");
    expect(toolNames).not.toContain("file_write");
    expect(toolNames).not.toContain("file_edit");

    // Plan mode has .gadget tools for its own storage
    expect(toolNames).toContain("plan_file_read");
    expect(toolNames).toContain("plan_file_write");
    expect(toolNames).toContain("plan_file_edit");
    expect(toolNames).toContain("plan_list");
  });

  it("exposes mutating file tools in build mode", () => {
    const toolNames = service.getToolNamesForMode(ChatSessionMode.Build);

    expect(toolNames).toContain("file_write");
    expect(toolNames).toContain("file_edit");

    // Build mode should not have Plan-only .gadget tools
    expect(toolNames).not.toContain("plan_file_read");
    expect(toolNames).not.toContain("plan_file_write");
    expect(toolNames).not.toContain("plan_file_edit");
    expect(toolNames).not.toContain("plan_list");
  });
});
