/**
 * #44 — pure construction of the wizard rows. Covers the two modes and the
 * strict id-only deduplication that keeps several OpenCode profiles distinct.
 */
import { describe, it, expect } from "vitest";

import type { AgentProfile } from "@/domain";
import { buildWizardEntries } from "./wizardEntries";

/** Minimal profile factory (only the fields the helper reads/carries). */
function profile(id: string, over: Partial<AgentProfile> = {}): AgentProfile {
  return {
    id,
    name: id,
    command: "claude",
    args: [],
    contextInjection: { strategy: "conventionFile", target: "CLAUDE.md" },
    detect: "claude --version",
    cwdTemplate: "{projectRoot}",
    ...over,
  };
}

const REFERENCES: AgentProfile[] = [
  profile("mock-claude", { name: "Claude Code", command: "claude" }),
  profile("mock-codex", { name: "Codex", command: "codex" }),
  profile("mock-opencode", {
    name: "OpenCode",
    command: "opencode",
    structuredAdapter: "openCode",
  }),
];

describe("buildWizardEntries — firstRun mode", () => {
  it("maps references to unselected rows with unknown availability", () => {
    const entries = buildWizardEntries({
      mode: "firstRun",
      configured: [],
      references: REFERENCES,
    });
    expect(entries).toHaveLength(3);
    expect(entries.every((e) => e.selected === false)).toBe(true);
    expect(entries.every((e) => e.available === null)).toBe(true);
    expect(entries.map((e) => e.profile.id)).toEqual([
      "mock-claude",
      "mock-codex",
      "mock-opencode",
    ]);
  });

  it("ignores configured profiles entirely in firstRun mode", () => {
    const entries = buildWizardEntries({
      mode: "firstRun",
      configured: [profile("mock-claude")],
      references: REFERENCES,
    });
    // Still exactly the reference rows, all unselected.
    expect(entries.map((e) => e.profile.id)).toEqual([
      "mock-claude",
      "mock-codex",
      "mock-opencode",
    ]);
    expect(entries.every((e) => e.selected === false)).toBe(true);
  });
});

describe("buildWizardEntries — edit mode", () => {
  it("puts configured profiles first, pre-selected, config intact", () => {
    const configured = [
      profile("cfg-oc-1", {
        name: "Local A",
        command: "opencode",
        structuredAdapter: "openCode",
        opencode: {
          baseURL: "http://localhost:9090/v1",
          apiKey: "sk-a",
          model: "qwen3-coder-14b",
        },
      }),
    ];
    const entries = buildWizardEntries({
      mode: "edit",
      configured,
      references: REFERENCES,
    });

    const first = entries[0];
    expect(first.profile.id).toBe("cfg-oc-1");
    expect(first.selected).toBe(true);
    // Real config carried through untouched.
    expect(first.profile.opencode?.baseURL).toBe("http://localhost:9090/v1");
    expect(first.profile.opencode?.model).toBe("qwen3-coder-14b");
    // Then all three references follow, unselected.
    expect(entries.slice(1).map((e) => e.profile.id)).toEqual([
      "mock-claude",
      "mock-codex",
      "mock-opencode",
    ]);
    expect(entries.slice(1).every((e) => e.selected === false)).toBe(true);
  });

  it("deduplicates by id only: a configured reference is not shown twice", () => {
    // The user edited the OpenCode reference and it is now configured under the
    // SAME id — it must appear once (the configured, pre-selected version wins).
    const configured = [
      profile("mock-opencode", {
        name: "OpenCode (edited)",
        command: "opencode",
        structuredAdapter: "openCode",
      }),
    ];
    const entries = buildWizardEntries({
      mode: "edit",
      configured,
      references: REFERENCES,
    });

    const ocRows = entries.filter((e) => e.profile.id === "mock-opencode");
    expect(ocRows).toHaveLength(1);
    expect(ocRows[0].selected).toBe(true);
    expect(ocRows[0].profile.name).toBe("OpenCode (edited)"); // configured wins
    // The other references remain (unselected).
    expect(entries.map((e) => e.profile.id)).toEqual([
      "mock-opencode",
      "mock-claude",
      "mock-codex",
    ]);
  });

  it("keeps several distinct OpenCode profiles that share command/adapter", () => {
    // Same command + structuredAdapter, different ids ⇒ distinct identities: all
    // preserved. Never matched/collapsed by command/adapter/endpoint/model.
    const configured = [
      profile("oc-1", {
        command: "opencode",
        structuredAdapter: "openCode",
        opencode: { baseURL: "http://a/v1", model: "m", apiKey: "" },
      }),
      profile("oc-2", {
        command: "opencode",
        structuredAdapter: "openCode",
        opencode: { baseURL: "http://b/v1", model: "m", apiKey: "" },
      }),
    ];
    const entries = buildWizardEntries({
      mode: "edit",
      configured,
      references: REFERENCES,
    });

    const ocIds = entries
      .filter((e) => e.profile.structuredAdapter === "openCode")
      .map((e) => e.profile.id);
    // Both configured OpenCode + the reference OpenCode (different id) survive.
    expect(ocIds).toEqual(["oc-1", "oc-2", "mock-opencode"]);
    expect(entries[0].selected).toBe(true);
    expect(entries[1].selected).toBe(true);
  });

  it("with no configured profiles behaves like references-only, still unselected", () => {
    const entries = buildWizardEntries({
      mode: "edit",
      configured: [],
      references: REFERENCES,
    });
    expect(entries.map((e) => e.profile.id)).toEqual([
      "mock-claude",
      "mock-codex",
      "mock-opencode",
    ]);
    expect(entries.every((e) => e.selected === false)).toBe(true);
  });
});
