import { beforeEach, describe, expect, it, vi } from "vitest";
import { getModel } from "../src/models.js";
import { streamSimple } from "../src/stream.js";
import type { Model } from "../src/types.js";

const mockState = vi.hoisted(() => ({
	lastParams: undefined as unknown,
}));

vi.mock("openai", () => {
	class FakeOpenAI {
		chat = {
			completions: {
				create: (params: unknown) => {
					mockState.lastParams = params;
					const stream = {
						async *[Symbol.asyncIterator]() {
							yield {
								choices: [{ delta: {}, finish_reason: "stop" }],
								usage: {
									prompt_tokens: 1,
									completion_tokens: 1,
									prompt_tokens_details: { cached_tokens: 0 },
									completion_tokens_details: { reasoning_tokens: 0 },
								},
							};
						},
					};
					const promise = Promise.resolve(stream) as Promise<typeof stream> & {
						withResponse: () => Promise<{
							data: typeof stream;
							response: { status: number; headers: Headers };
						}>;
					};
					promise.withResponse = async () => ({
						data: stream,
						response: { status: 200, headers: new Headers() },
					});
					return promise;
				},
			},
		};
	}

	return { default: FakeOpenAI };
});

function userContext() {
	return {
		messages: [{ role: "user" as const, content: "hi", timestamp: Date.now() }],
	};
}

describe("openai-completions always-thinking models", () => {
	beforeEach(() => {
		mockState.lastParams = undefined;
	});

	it("keeps thinking enabled for zai models that cannot disable it", async () => {
		const model = getModel("zai", "glm-5.3")!;
		expect(model.thinkingLevelMap?.off).toBeNull();

		await streamSimple(model, userContext(), { apiKey: "test" }).result();

		const params = mockState.lastParams as { enable_thinking?: boolean };
		expect(params.enable_thinking).toBe(true);
	});

	it("clamps an explicit off request to the lowest supported level", async () => {
		const model = getModel("zai", "glm-5.3")!;

		await streamSimple(model, userContext(), { apiKey: "test", reasoning: "off" }).result();

		const params = mockState.lastParams as { enable_thinking?: boolean };
		expect(params.enable_thinking).toBe(true);
	});

	it("still sends an explicit disable for zai models that support it", async () => {
		const model = getModel("zai", "glm-5.2")!;
		expect(model.thinkingLevelMap?.off).not.toBeNull();

		await streamSimple(model, userContext(), { apiKey: "test" }).result();

		const params = mockState.lastParams as { enable_thinking?: boolean };
		expect(params.enable_thinking).toBe(false);
	});

	it("enables effort requests on zai models that cannot disable thinking", async () => {
		const model = getModel("zai", "glm-5.3")!;

		await streamSimple(model, userContext(), { apiKey: "test", reasoning: "low" }).result();

		const params = mockState.lastParams as { enable_thinking?: boolean };
		expect(params.enable_thinking).toBe(true);
	});

	it("keeps deepseek-format thinking enabled when off is unsupported", async () => {
		const base = getModel("deepseek", "deepseek-v4-flash")!;
		const model = {
			...base,
			thinkingLevelMap: { off: null, low: "low", high: "high" },
		} as Model<"openai-completions">;

		await streamSimple(model, userContext(), { apiKey: "test" }).result();

		const params = mockState.lastParams as { thinking?: { type?: string } };
		expect(params.thinking?.type).toBe("enabled");
	});
});
