import { test } from "node:test";
import assert from "node:assert/strict";
import { getLocalCatalog, canonicalForCategory } from "../servers/gateway/capability-registry.js";

const db = {
  async execute() {
    return { rows: [
      { bot_id: "a", display_name: "A", enabled: 1, project_id: null, definition: JSON.stringify({ models: { default: "m1" }, tools: { crow_mcp: ["crow-memory/x"] }, system_prompt: "SENTINEL_SECRET_LEAK" }) },
      { bot_id: "b", display_name: "B", enabled: 0, project_id: 3, definition: "{}" },
    ] };
  },
};

test("catalog includes core tools with canonical+category and a positive count", async () => {
  const cat = await getLocalCatalog(db, { crowHome: "/tmp/nonexistent-crowhome", instanceId: "self", instanceName: "Self" });
  const mem = cat.tools.find((t) => t.canonicalId === canonicalForCategory("memory"));
  assert.ok(mem, "memory core tool present");
  assert.equal(mem.category, "memory");
  assert.ok(mem.toolCount > 0);
});

test("catalog projects bots public-safe (no definition leak)", async () => {
  const cat = await getLocalCatalog(db, { crowHome: "/tmp/nonexistent-crowhome", instanceId: "self" });
  assert.equal(cat.bots.length, 2);
  assert.equal(cat.bots[0].model, "m1");
  assert.equal(cat.bots[0].tool_count, 1);
  assert.ok(!JSON.stringify(cat.bots).includes("definition"));
  assert.ok(!JSON.stringify(cat.bots).includes("SENTINEL_SECRET_LEAK"), "system_prompt must not leak");
  assert.equal(cat.instanceId, "self");
});

test("catalog reflects the exposure set on tool entries", async () => {
  // db stub: exposure setting returns ["crow-memory"]; bot query returns [].
  const exposingDb = {
    async execute({ sql }) {
      if (/dashboard_settings_overrides/.test(sql)) return { rows: [] };
      if (/FROM dashboard_settings\b/.test(sql)) return { rows: [{ value: JSON.stringify(["crow-memory"]) }] };
      return { rows: [] }; // pi_bot_defs
    },
  };
  const cat = await getLocalCatalog(exposingDb, { crowHome: "/tmp/nonexistent-crowhome", instanceId: "self" });
  const mem = cat.tools.find((t) => t.canonicalId === canonicalForCategory("memory"));
  assert.equal(mem.exposed, true);
  const others = cat.tools.filter((t) => t.canonicalId !== "crow-memory");
  assert.ok(others.every((t) => t.exposed === false), "non-exposed tools are exposed:false");
});
