import { afterAll, beforeEach, describe, expect, it } from "vitest";
import { DatabaseRuntimeSettings } from "../../src/settings/runtime.js";
import { DEFAULT_ORG_ID, prisma, resetDb, seedTestOrganization, testSecretEnvelope } from "./helpers.js";

describe("Organization-scoped Agent runtime configuration", () => {
  beforeEach(async () => {
    await resetDb();
  });

  afterAll(async () => {
    await prisma.$disconnect();
  });

  it("resolves role prompt, model, tools and skills from the project Organization", async () => {
    await seedTestOrganization("org_other", "other");
    await Promise.all([
      prisma.project.create({
        data: { id: "project-a", organizationId: DEFAULT_ORG_ID, name: "A", workspaceDir: "/tmp/a" },
      }),
      prisma.project.create({
        data: { id: "project-b", organizationId: "org_other", name: "B", workspaceDir: "/tmp/b" },
      }),
    ]);
    const [skillA, skillB] = await Promise.all([
      prisma.organizationAgentSkill.create({
        data: {
          id: "skill-a",
          organizationId: DEFAULT_ORG_ID,
          name: "typst",
          version: "0.15.0",
          contentDigest: "a".repeat(64),
        },
      }),
      prisma.organizationAgentSkill.create({
        data: {
          id: "skill-b",
          organizationId: "org_other",
          name: "typst",
          version: "other",
          contentDigest: "b".repeat(64),
        },
      }),
    ]);
    const [roleA, roleB] = await Promise.all([
      prisma.organizationAgentRole.update({
        where: { organizationId_roleId: { organizationId: DEFAULT_ORG_ID, roleId: "draft" } },
        data: {
          label: "A Draft",
          defaultModel: "anthropic/claude-sonnet-5",
          systemPrompt: "prompt-a",
          tools: ["read_file", "cph_build"],
        },
      }),
      prisma.organizationAgentRole.update({
        where: { organizationId_roleId: { organizationId: "org_other", roleId: "draft" } },
        data: {
          label: "B Draft",
          systemPrompt: "prompt-b",
          tools: [],
        },
      }),
    ]);
    await Promise.all([
      prisma.organizationAgentRoleSkill.create({
        data: { organizationId: DEFAULT_ORG_ID, agentRoleId: roleA.id, agentSkillId: skillA.id },
      }),
      prisma.organizationAgentRoleSkill.create({
        data: { organizationId: "org_other", agentRoleId: roleB.id, agentSkillId: skillB.id },
      }),
    ]);
    const settings = new DatabaseRuntimeSettings(prisma, testSecretEnvelope, {});

    const registryA = await settings.modelRegistry({ projectId: "project-a" });
    const registryB = await settings.modelRegistry({ projectId: "project-b" });

    expect(registryA.role("draft")).toMatchObject({
      label: "A Draft",
      systemPrompt: "prompt-a",
      tools: ["read_file", "cph_build"],
      skills: [{ name: "typst", version: "0.15.0", contentDigest: "a".repeat(64) }],
    });
    expect(registryB.role("draft")).toMatchObject({
      label: "B Draft",
      systemPrompt: "prompt-b",
      tools: [],
      skills: [{ name: "typst", version: "other", contentDigest: "b".repeat(64) }],
    });
  });

  it("fails closed for missing scope and disabled role skills", async () => {
    await prisma.project.create({
      data: { id: "project-a", organizationId: DEFAULT_ORG_ID, name: "A", workspaceDir: "/tmp/a" },
    });
    const skill = await prisma.organizationAgentSkill.create({
      data: {
        id: "skill-disabled",
        organizationId: DEFAULT_ORG_ID,
        name: "typst",
        version: "0.15.0",
        contentDigest: "c".repeat(64),
        disabledAt: new Date(),
      },
    });
    const role = await prisma.organizationAgentRole.findUniqueOrThrow({
      where: { organizationId_roleId: { organizationId: DEFAULT_ORG_ID, roleId: "draft" } },
    });
    await prisma.organizationAgentRoleSkill.create({
      data: { organizationId: DEFAULT_ORG_ID, agentRoleId: role.id, agentSkillId: skill.id },
    });
    const settings = new DatabaseRuntimeSettings(prisma, testSecretEnvelope, {});

    await expect(settings.modelRegistry()).rejects.toThrow("projectId is required");
    await expect(settings.modelRegistry({ projectId: "project-a" })).rejects.toThrow(
      "role draft selects disabled skill typst",
    );
  });
});
