import { describe, expect, it } from "vitest";
import { createAgentProfileRegistry, type AgentProfile } from "./profile-registry.js";

describe("agent profile registry", () => {
  it("resolves AgentDefinition tool whitelist and blacklist against available tools", () => {
    const registry = createAgentProfileRegistry(
      [
        {
          description: "Custom agent",
          disallowedTools: ["shell"],
          name: "custom",
          source: "user",
          tools: ["*", "unknown-tool"],
        },
      ],
      ["echo", "read-file", "shell"],
    );

    expect(registry.require("custom").allowedTools).toEqual(["echo", "read-file"]);
  });

  it("filters explicit AgentDefinition tool lists down to installed tools", () => {
    const registry = createAgentProfileRegistry(
      [
        {
          description: "Reader",
          maxProviderTurns: 3,
          name: "reader",
          source: "project",
          tools: ["read-file", "missing-tool"],
        },
      ],
      ["echo", "read-file"],
    );

    expect(registry.require("reader").allowedTools).toEqual(["read-file"]);
    expect(registry.require("reader").maxProviderTurns).toBe(3);
  });

  it("keeps legacy AgentProfile inputs unchanged", () => {
    const legacyProfile: AgentProfile = {
      allowedTools: ["echo"],
      description: "Legacy",
      name: "legacy",
      source: "extension",
    };
    const registry = createAgentProfileRegistry([legacyProfile], ["echo", "read-file"]);

    expect(registry.require("legacy")).toMatchObject({
      allowedTools: ["echo"],
      description: "Legacy",
      name: "legacy",
      source: "extension",
    });
  });

  it("lets later definitions override earlier ones by name", () => {
    const registry = createAgentProfileRegistry(
      [
        {
          description: "First",
          name: "dup",
          source: "user",
          tools: ["echo"],
        },
        {
          description: "Second",
          name: "dup",
          source: "project",
          tools: ["read-file"],
        },
      ],
      ["echo", "read-file"],
    );

    expect(registry.require("dup")).toMatchObject({
      allowedTools: ["read-file"],
      description: "Second",
      name: "dup",
      source: "project",
    });
  });

  it("exposes lsp tools to built-in coding profiles and keeps them out of compact", () => {
    const registry = createAgentProfileRegistry(
      [],
      [
        "echo",
        "read-file",
        "lsp-goto-definition",
        "lsp-find-references",
        "lsp-diagnostics",
        "lsp-symbol-search",
        "fetch-url",
      ],
    );

    for (const profileName of ["orchestrator", "explore", "plan", "build", "verify"] as const) {
      expect(registry.require(profileName).allowedTools).toContain("lsp-diagnostics");
      expect(registry.require(profileName).allowedTools).toContain("lsp-goto-definition");
      expect(registry.require(profileName).allowedTools).toContain("lsp-symbol-search");
      expect(registry.require(profileName).allowedTools).toContain("web-search");
    }
    expect(registry.require("compact").allowedTools).not.toContain("lsp-diagnostics");
    expect(registry.require("compact").allowedTools).not.toContain("lsp-goto-definition");
  });

  it("keeps implementation prompts on orchestrator unless an explicit profile prefix is used", () => {
    const registry = createAgentProfileRegistry();

    expect(
      registry.resolve({
        prompt:
          "Your task is to implement a command line tool in the current workspace and create the required deliverables.",
      }).profile.name,
    ).toBe("orchestrator");

    expect(
      registry.resolve({
        prompt: "Fix the failing implementation in the current workspace before you finish.",
      }).profile.name,
    ).toBe("orchestrator");

    const routed = registry.resolve({
      prompt: "build: Fix the failing implementation in the current workspace before you finish.",
    });
    expect(routed.profile.name).toBe("build");
    expect(routed.prompt).toBe(
      "Fix the failing implementation in the current workspace before you finish.",
    );
  });

  it("keeps build profile finalization tied to requested verification", () => {
    const registry = createAgentProfileRegistry();

    expect(registry.require("build").systemPrompt).toContain(
      "Before final, run the user's requested smoke checks or artifact-producing commands yourself when tools permit",
    );
  });

  it("keeps git commit scope selection explicit for commit-capable profiles", () => {
    const registry = createAgentProfileRegistry();

    for (const profileName of ["orchestrator", "build"] as const) {
      const prompt = registry.require(profileName).systemPrompt;
      expect(prompt).toContain("Before creating a git commit, inspect git status");
      expect(prompt).toContain(
        "choose between current-thread changes, staged changes, unstaged changes, or all changes",
      );
      expect(prompt).toContain("commit only the selected scope");
    }
  });

  it("keeps non-implementation task prompts on the orchestrator profile", () => {
    const registry = createAgentProfileRegistry();

    expect(
      registry.resolve({
        prompt: "Your task is to summarize the project status for the team.",
      }).profile.name,
    ).toBe("orchestrator");
  });
});
