import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
import { mkdtemp, rm, readFile, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
vi.mock("../../utils/logger.js", () => ({
    logger: { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() },
}));
describe("config", () => {
    let tempDir;
    let configDir;
    beforeEach(async () => {
        tempDir = await mkdtemp(join(tmpdir(), "pocketcoder-config-test-"));
        configDir = tempDir;
    });
    afterEach(async () => {
        vi.restoreAllMocks();
        await rm(tempDir, { recursive: true, force: true });
    });
    async function importConfig() {
        vi.resetModules();
        vi.doMock("../../utils/paths.js", () => ({
            getConfigDir: () => configDir,
        }));
        vi.doMock("../../utils/logger.js", () => ({
            logger: { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() },
        }));
        return import("../index.js");
    }
    describe("loadConfig", () => {
        it("should create default config if config.json does not exist", async () => {
            const { loadConfig, DEFAULT_CONFIG } = await importConfig();
            const config = await loadConfig();
            expect(config).toEqual(DEFAULT_CONFIG);
            // Verify file was created
            const raw = await readFile(join(configDir, "config.json"), "utf-8");
            const saved = JSON.parse(raw);
            expect(saved).toEqual(DEFAULT_CONFIG);
        });
        it("should load existing config.json", async () => {
            const userConfig = {
                machineLabel: "My Laptop",
                opencode: { port: 5000 },
                fileWatcher: { debounceMs: 200, maxChangesPerMessage: 100 },
                terminal: { maxTerminals: 3 },
            };
            await writeFile(join(configDir, "config.json"), JSON.stringify(userConfig), "utf-8");
            const { loadConfig } = await importConfig();
            const config = await loadConfig();
            expect(config.machineLabel).toBe("My Laptop");
            expect(config.opencode.port).toBe(5000);
            expect(config.fileWatcher.debounceMs).toBe(200);
            expect(config.fileWatcher.maxChangesPerMessage).toBe(100);
            expect(config.terminal.maxTerminals).toBe(3);
        });
        it("should merge user config with defaults", async () => {
            // Only provide partial config - defaults should fill the rest
            const userConfig = {
                machineLabel: "Test Machine",
                gatewayUrl: "wss://custom.example.com",
            };
            await writeFile(join(configDir, "config.json"), JSON.stringify(userConfig), "utf-8");
            const { loadConfig, DEFAULT_CONFIG } = await importConfig();
            const config = await loadConfig();
            expect(config.machineLabel).toBe("Test Machine");
            expect(config.gatewayUrl).toBe("wss://custom.example.com");
            // Defaults should be preserved
            expect(config.opencode.port).toBe(DEFAULT_CONFIG.opencode.port);
            expect(config.fileWatcher.debounceMs).toBe(DEFAULT_CONFIG.fileWatcher.debounceMs);
            expect(config.terminal.maxTerminals).toBe(DEFAULT_CONFIG.terminal.maxTerminals);
        });
        it("should deep merge nested objects", async () => {
            // Only override one nested field
            const userConfig = {
                opencode: { port: 8080 },
            };
            await writeFile(join(configDir, "config.json"), JSON.stringify(userConfig), "utf-8");
            const { loadConfig, DEFAULT_CONFIG } = await importConfig();
            const config = await loadConfig();
            expect(config.opencode.port).toBe(8080);
            // Other defaults should remain
            expect(config.fileWatcher.debounceMs).toBe(DEFAULT_CONFIG.fileWatcher.debounceMs);
        });
        it("should fall back to defaults for invalid JSON", async () => {
            await writeFile(join(configDir, "config.json"), "{ invalid json }", "utf-8");
            const { loadConfig, DEFAULT_CONFIG } = await importConfig();
            const config = await loadConfig();
            expect(config).toEqual(DEFAULT_CONFIG);
        });
        it("should fall back to defaults when validation fails", async () => {
            const invalidConfig = {
                opencode: { port: -1 },
                fileWatcher: { debounceMs: 300, maxChangesPerMessage: 500 },
                terminal: { maxTerminals: 5 },
            };
            await writeFile(join(configDir, "config.json"), JSON.stringify(invalidConfig), "utf-8");
            const { loadConfig, DEFAULT_CONFIG } = await importConfig();
            const config = await loadConfig();
            expect(config).toEqual(DEFAULT_CONFIG);
        });
    });
    describe("saveConfig", () => {
        it("should save config to config.json", async () => {
            const { saveConfig, DEFAULT_CONFIG } = await importConfig();
            const config = { ...DEFAULT_CONFIG, machineLabel: "Saved Machine" };
            await saveConfig(config);
            const raw = await readFile(join(configDir, "config.json"), "utf-8");
            const saved = JSON.parse(raw);
            expect(saved.machineLabel).toBe("Saved Machine");
        });
    });
    describe("validateConfig", () => {
        it("should accept valid config", async () => {
            const { validateConfig, DEFAULT_CONFIG } = await importConfig();
            const errors = validateConfig(DEFAULT_CONFIG);
            expect(errors).toEqual([]);
        });
        it("should reject invalid gatewayUrl", async () => {
            const { validateConfig, DEFAULT_CONFIG } = await importConfig();
            const config = { ...DEFAULT_CONFIG, gatewayUrl: "http://not-websocket.com" };
            const errors = validateConfig(config);
            expect(errors).toContain("gatewayUrl must start with ws:// or wss://");
        });
        it("should reject invalid opencode port", async () => {
            const { validateConfig, DEFAULT_CONFIG } = await importConfig();
            const config = { ...DEFAULT_CONFIG, opencode: { port: 99999 } };
            const errors = validateConfig(config);
            expect(errors).toContain("opencode.port must be a number between 1 and 65535");
        });
        it("should reject invalid terminal maxTerminals", async () => {
            const { validateConfig, DEFAULT_CONFIG } = await importConfig();
            const config = { ...DEFAULT_CONFIG, terminal: { maxTerminals: 0 } };
            const errors = validateConfig(config);
            expect(errors).toContain("terminal.maxTerminals must be a positive number");
        });
        it("should reject negative debounceMs", async () => {
            const { validateConfig, DEFAULT_CONFIG } = await importConfig();
            const config = {
                ...DEFAULT_CONFIG,
                fileWatcher: { ...DEFAULT_CONFIG.fileWatcher, debounceMs: -1 },
            };
            const errors = validateConfig(config);
            expect(errors).toContain("fileWatcher.debounceMs must be a non-negative number");
        });
    });
});
//# sourceMappingURL=index.test.js.map