import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { listModelsForService, resolveServiceModelsBaseUrl } from "../llm/service-presets.js";
describe("listModelsForService (B8)", () => {
    const originalEnv = process.env.INKOS_LLM_MODEL;
    const originalFetch = global.fetch;
    beforeEach(() => {
        delete process.env.INKOS_LLM_MODEL;
    });
    afterEach(() => {
        if (originalEnv)
            process.env.INKOS_LLM_MODEL = originalEnv;
        else
            delete process.env.INKOS_LLM_MODEL;
        global.fetch = originalFetch;
    });
    it("anthropic service 无 apikey 时返回 provider 内置 enabled 子集", async () => {
        const models = await listModelsForService("anthropic");
        expect(models.length).toBeGreaterThan(0);
        expect(models.some((m) => m.id === "claude-sonnet-4-6")).toBe(true);
        const sonnet = models.find((m) => m.id === "claude-sonnet-4-6");
        expect(sonnet?.maxOutput).toBe(64_000);
        expect(sonnet?.contextWindow).toBe(1_000_000);
    });
    it("google service 的文本模型列表不包含 image preview 模型", async () => {
        const models = await listModelsForService("google");
        expect(models.some((m) => m.id === "gemini-2.5-flash")).toBe(true);
        expect(models.some((m) => m.id.includes("image"))).toBe(false);
    });
    it("custom service 走 live probe + bank 补元数据", async () => {
        global.fetch = vi.fn().mockResolvedValue({
            ok: true,
            json: async () => ({ data: [{ id: "gpt-4o" }, { id: "my-proxy-model" }] }),
        });
        const models = await listModelsForService("custom", "sk-test", "https://myproxy.example/v1");
        // gpt-4o 命中 openai provider，拿到元数据
        const gpt = models.find((m) => m.id === "gpt-4o");
        expect(gpt).toBeDefined();
        expect(gpt?.maxOutput).toBe(4096);
        // 自定义 id 没元数据也保留
        expect(models.some((m) => m.id === "my-proxy-model")).toBe(true);
    });
    it("ollama 无 apiKey 时也探测本地 /models 并保留本地动态模型", async () => {
        const fetchMock = vi.fn().mockResolvedValue({
            ok: true,
            json: async () => ({ data: [{ id: "qwen3.6:35b-a3b" }] }),
        });
        global.fetch = fetchMock;
        const models = await listModelsForService("ollama");
        expect(fetchMock).toHaveBeenCalledWith("http://localhost:11434/v1/models", expect.any(Object));
        expect(models.some((m) => m.id === "qwen3.6:35b-a3b")).toBe(true);
    });
    it("R4：env 补丁已删除 — INKOS_LLM_MODEL 不再污染跨 service 菜单", async () => {
        process.env.INKOS_LLM_MODEL = "my-secret-model";
        const models = await listModelsForService("anthropic");
        // my-secret-model 不在 anthropic bank → 不应该出现
        expect(models.some((m) => m.id === "my-secret-model")).toBe(false);
    });
    it("live 挂了降级到 provider 内置 models（没有 fetch 错误 crash）", async () => {
        global.fetch = vi.fn().mockRejectedValue(new Error("ECONNREFUSED"));
        const models = await listModelsForService("anthropic", "sk-test");
        expect(models.length).toBeGreaterThan(0);
        expect(models.some((m) => m.id === "claude-sonnet-4-6")).toBe(true);
    });
    it("bailian 不用 OpenAI 兼容 /models 污染 Anthropic 通道模型列表", async () => {
        const fetchMock = vi.fn().mockImplementation(async (input) => {
            const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
            if (url === "https://dashscope.aliyuncs.com/compatible-mode/v1/models") {
                return {
                    ok: true,
                    json: async () => ({ data: [{ id: "kimi-k2.6" }, { id: "deepseek-v3.2" }] }),
                };
            }
            return {
                ok: false,
                json: async () => ({ data: [] }),
            };
        });
        global.fetch = fetchMock;
        const models = await listModelsForService("bailian", "sk-test");
        expect(resolveServiceModelsBaseUrl("bailian")).toBe("https://dashscope.aliyuncs.com/apps/anthropic");
        expect(fetchMock).not.toHaveBeenCalledWith("https://dashscope.aliyuncs.com/compatible-mode/v1/models", expect.any(Object));
        expect(models.some((m) => m.id === "qwen-turbo")).toBe(true);
        expect(models.some((m) => m.id === "kimi-k2.6")).toBe(false);
        expect(models.some((m) => m.id === "deepseek-v3.2")).toBe(false);
    });
    it("未知 service 返回空数组", async () => {
        const models = await listModelsForService("nonexistent-xyz");
        expect(models).toEqual([]);
    });
});
//# sourceMappingURL=list-models.test.js.map