import assert from "node:assert/strict";
import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, beforeEach, test } from "vitest";

import { loadGatewayConfigFromEnv } from "../memory-embeddings.js";

const ENV_KEYS = [
	"SF_LLM_GATEWAY_EMBED_MODEL",
	"SF_LLM_GATEWAY_RERANK_MODEL",
	"SF_LLM_GATEWAY_EMBED_QUERY_INSTRUCTION",
	"SF_LLM_GATEWAY_KEY",
	"SF_LLM_GATEWAY_URL",
];

let originalHome;
let tmpHome;

beforeEach(() => {
	originalHome = process.env.HOME;
	tmpHome = mkdtempSync(join(tmpdir(), "sf-test-"));
	mkdirSync(join(tmpHome, ".sf", "agent"), { recursive: true });
	process.env.HOME = tmpHome;
});

afterEach(() => {
	process.env.HOME = originalHome;
	for (const key of ENV_KEYS) delete process.env[key];
});

function writeAuthJson(entry) {
	const authPath = join(tmpHome, ".sf", "agent", "auth.json");
	writeFileSync(authPath, JSON.stringify({ "llm-gateway": entry }));
}

test("loadGatewayConfigFromEnv returns null when auth.json has no llm-gateway entry and no env key", () => {
	const authPath = join(tmpHome, ".sf", "agent", "auth.json");
	writeFileSync(authPath, JSON.stringify({}));
	delete process.env.SF_LLM_GATEWAY_KEY;
	assert.equal(loadGatewayConfigFromEnv(), null);
});

test("loadGatewayConfigFromEnv returns null when auth.json does not exist and no env key", () => {
	delete process.env.SF_LLM_GATEWAY_KEY;
	assert.equal(loadGatewayConfigFromEnv(), null);
});

test("loadGatewayConfigFromEnv falls back to SF_LLM_GATEWAY_KEY env var when auth.json missing", () => {
	process.env.SF_LLM_GATEWAY_KEY = "env-key-123";
	process.env.SF_LLM_GATEWAY_URL = "https://env.example/v1";
	const cfg = loadGatewayConfigFromEnv();
	assert.equal(cfg.apiKey, "env-key-123");
	assert.equal(cfg.url, "https://env.example/v1");
	assert.equal(cfg.keySource, "env:SF_LLM_GATEWAY_KEY");
	assert.equal(cfg.urlSource, "env:SF_LLM_GATEWAY_KEY");
});

test("loadGatewayConfigFromEnv falls back to SF_LLM_GATEWAY_KEY env var when auth.json has no key", () => {
	const authPath = join(tmpHome, ".sf", "agent", "auth.json");
	writeFileSync(authPath, JSON.stringify({}));
	process.env.SF_LLM_GATEWAY_KEY = "env-key-456";
	delete process.env.SF_LLM_GATEWAY_URL;
	const cfg = loadGatewayConfigFromEnv();
	assert.equal(cfg.apiKey, "env-key-456");
	assert.equal(cfg.url, "https://llm-gateway.centralcloud.com/v1");
	assert.equal(cfg.keySource, "env:SF_LLM_GATEWAY_KEY");
	assert.equal(cfg.urlSource, "default");
});

test("loadGatewayConfigFromEnv prefers auth.json over env var when both present", () => {
	writeAuthJson({
		key: "auth-key",
		url: "https://auth.example/v1",
		type: "api_key",
	});
	process.env.SF_LLM_GATEWAY_KEY = "env-key-789";
	process.env.SF_LLM_GATEWAY_URL = "https://env.example/v1";
	const cfg = loadGatewayConfigFromEnv();
	assert.equal(cfg.apiKey, "auth-key");
	assert.equal(cfg.url, "https://auth.example/v1");
	assert.equal(cfg.keySource, "auth.json:llm-gateway");
});

test("loadGatewayConfigFromEnv reads key and url from auth.json", () => {
	writeAuthJson({
		key: "auth-key",
		url: "https://example.test/v1",
		type: "api_key",
	});

	const cfg = loadGatewayConfigFromEnv();
	assert.equal(cfg.apiKey, "auth-key");
	assert.equal(cfg.url, "https://example.test/v1");
	assert.equal(cfg.keySource, "auth.json:llm-gateway");
	assert.equal(cfg.urlSource, "auth.json:llm-gateway");
	assert.equal(cfg.embeddingModel, "Qwen/Qwen3-Embedding-4B");
	assert.equal(cfg.rerankModel, "Qwen/Qwen3-Reranker-0.6B");
});

test("loadGatewayConfigFromEnv uses default url when auth.json has no url", () => {
	writeAuthJson({ key: "auth-key", type: "api_key" });

	const cfg = loadGatewayConfigFromEnv();
	assert.equal(cfg.url, "https://llm-gateway.centralcloud.com/v1");
	assert.equal(cfg.urlSource, "default");
});

test("loadGatewayConfigFromEnv respects model env var overrides", () => {
	writeAuthJson({ key: "auth-key", type: "api_key" });
	process.env.SF_LLM_GATEWAY_EMBED_MODEL = "custom-embed";
	process.env.SF_LLM_GATEWAY_RERANK_MODEL = "custom-rerank";

	const cfg = loadGatewayConfigFromEnv();
	assert.equal(cfg.embeddingModel, "custom-embed");
	assert.equal(cfg.rerankModel, "custom-rerank");
});
