import { promises as fs } from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
const detectToolStatusesMock = vi.fn();
const ensureToolsInstalledMock = vi.fn();
const installSkillPackageToSdkMock = vi.fn();
const runCcSwitchAdapterMock = vi.fn();
vi.mock('./tool-installer.js', () => ({
    detectToolStatuses: detectToolStatusesMock,
    ensureToolsInstalled: ensureToolsInstalledMock,
}));
vi.mock('./cc-switch-sdk.js', () => ({
    loadCcSwitchSdk: vi.fn(async () => activeSdk),
    runCcSwitchAdapter: runCcSwitchAdapterMock,
    toSdkAppsFromEnabledTools: (enabledTools) => {
        const tools = Array.isArray(enabledTools) ? enabledTools : [];
        return {
            claude: false,
            acode: false,
            claudecode: tools.includes('claude') || tools.includes('claudecode'),
            codex: tools.includes('codex'),
            gemini: tools.includes('gemini'),
            opencode: tools.includes('opencode'),
            openclaw: tools.includes('openclaw'),
        };
    },
}));
vi.mock('../utils/file-utils.js', async (importOriginal) => {
    const original = await importOriginal();
    return {
        ...original,
        installSkillPackageToSdk: installSkillPackageToSdkMock,
    };
});
class MockSdk {
    constructor() {
        this.createdMcpInputs = [];
        this.installedSkills = [];
        this.mcpServers = [];
    }
    getAllSkills() {
        return this.installedSkills;
    }
    getAllMcpServers() {
        return this.mcpServers;
    }
    async createMcpServer(input) {
        this.createdMcpInputs.push({ name: input.name, apps: input.apps });
        const server = {
            id: `mcp-${this.mcpServers.length + 1}`,
            name: input.name,
            server: input.server,
            apps: input.apps,
        };
        this.mcpServers.push(server);
        return server;
    }
    async updateMcpServer(id, input) {
        const existing = this.mcpServers.find((server) => server.id === id);
        if (!existing) {
            throw new Error(`missing mcp ${id}`);
        }
        if (input.apps) {
            existing.apps = input.apps;
        }
        if (input.server) {
            existing.server = input.server;
        }
        return existing;
    }
}
let activeSdk;
function status(tool, installed) {
    return {
        tool,
        installed,
        executable: installed ? tool : null,
        version: installed ? '1.0.0' : null,
        installing: false,
        error: installed ? null : 'not installed',
    };
}
describe('initInstance enabled tool initialization', () => {
    const originalRuntimeHomeDir = process.env.AWS_RUNTIME_HOME_DIR;
    let runtimeHomeDir;
    beforeEach(async () => {
        runtimeHomeDir = path.join(os.tmpdir(), `aws-init-enabled-tools-${Date.now()}`);
        process.env.AWS_RUNTIME_HOME_DIR = runtimeHomeDir;
        activeSdk = new MockSdk();
        vi.clearAllMocks();
        runCcSwitchAdapterMock.mockResolvedValue({ ok: true, snapshot: { skills: 0, mcpServers: 0 } });
        installSkillPackageToSdkMock.mockImplementation(async (_sdk, skillPackage, _skillDir, apps) => {
            const installed = {
                id: 'skill-1',
                name: String(skillPackage.skillName || 'demo-skill'),
                directory: '/demo-skill',
                apps,
                installedAt: Date.now(),
            };
            activeSdk.installedSkills.push(installed);
            return installed;
        });
    });
    afterEach(async () => {
        if (originalRuntimeHomeDir === undefined) {
            delete process.env.AWS_RUNTIME_HOME_DIR;
        }
        else {
            process.env.AWS_RUNTIME_HOME_DIR = originalRuntimeHomeDir;
        }
        await fs.rm(runtimeHomeDir, { recursive: true, force: true });
    });
    it('persists requested tools but configures MCP and skills only for installed tools', async () => {
        detectToolStatusesMock.mockResolvedValue({
            claude: status('claude', true),
            opencode: status('opencode', false),
            codex: status('codex', false),
        });
        const { initInstance } = await import('./instance-init-service.js');
        const result = await initInstance('agent-installed-only', runtimeHomeDir, {
            ccSwitchEnabledTools: ['claude', 'opencode', 'codex'],
            skillPackages: [{ skillName: 'demo-skill', downloadUrl: 'https://example.com/skill.zip' }],
            mcpServers: [{ name: 'aws-mcp', command: 'node', args: ['server.js'] }],
        });
        expect(ensureToolsInstalledMock).not.toHaveBeenCalled();
        expect(result.enabledTools).toEqual(['claude', 'opencode', 'codex']);
        expect(result.ok).toBe(true);
        expect(installSkillPackageToSdkMock).toHaveBeenCalledWith(activeSdk, expect.objectContaining({ skillName: 'demo-skill' }), expect.any(String), expect.objectContaining({ claudecode: true, opencode: false, codex: false }));
        expect(activeSdk.createdMcpInputs).toEqual([
            {
                name: 'aws-mcp',
                apps: expect.objectContaining({ claudecode: true, opencode: false, codex: false }),
            },
        ]);
        const statePath = path.join(runtimeHomeDir, '.aws-bridge', 'instances', 'agent-installed-only', 'state.json');
        const state = JSON.parse(await fs.readFile(statePath, 'utf-8'));
        expect(state.enabledTools).toEqual(['claude', 'opencode', 'codex']);
    });
});
