/**
 * OpenCode MCP Adapter
 *
 * 实现 IMcpAdapter 接口，负责 OpenCode 的 MCP 配置读写
 */
import { toMcpSpecFromOpenCode, toOpenCodeServer } from './common.js';
/**
 * JSON 文件读取工具
 */
async function readJsonFile(filePath, fallback) {
    try {
        const raw = await import('node:fs/promises').then(fs => fs.readFile(filePath, "utf-8"));
        const parsed = JSON.parse(raw);
        if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
            return parsed;
        }
        return { ...fallback };
    }
    catch {
        return { ...fallback };
    }
}
/**
 * JSON 文件写入工具
 */
async function writeJsonFile(filePath, content) {
    const fs = await import('node:fs/promises');
    const path = await import('node:path');
    const parent = path.dirname(filePath);
    await fs.mkdir(parent, { recursive: true });
    await fs.writeFile(filePath, JSON.stringify(content, null, 2), "utf-8");
}
/**
 * 生成唯一 ID
 */
function createId(prefix) {
    const timestamp = Date.now().toString(36);
    const random = Math.random().toString(36).slice(2, 8);
    return `${prefix}_${timestamp}_${random}`;
}
export class OpenCodeMcpAdapter {
    constructor(configPath) {
        this.configPath = configPath;
        this.appId = "opencode";
    }
    /**
     * 读取 OpenCode MCP 映射，优先使用合法的 mcp 字段，兼容历史错误写入的 mcpServers。
     */
    getMcpMap(config) {
        const mcp = config.mcp && typeof config.mcp === "object" ? config.mcp : {};
        const legacyMcpServers = config.mcpServers && typeof config.mcpServers === "object" ? config.mcpServers : {};
        return { ...legacyMcpServers, ...mcp };
    }
    /**
     * 将 MCP 服务器写回 OpenCode 配置，只保留合法的 mcp 字段并清理错误的 mcpServers。
     */
    async saveMcpMap(config, mcp) {
        config.mcp = mcp;
        if ("mcpServers" in config) {
            delete config.mcpServers;
        }
        await writeJsonFile(this.configPath, config);
    }
    async importServers() {
        const config = await readJsonFile(this.configPath, {});
        const entries = Object.entries(this.getMcpMap(config));
        return entries.map(([name, server]) => ({
            id: createId("mcp"),
            name,
            server: toMcpSpecFromOpenCode(server),
            apps: {
                claude: false,
                claudecode: false,
                codex: false,
                gemini: false,
                opencode: true,
                openclaw: false,
            },
        }));
    }
    async syncServer(server) {
        const config = await readJsonFile(this.configPath, {});
        const mcp = this.getMcpMap(config);
        mcp[server.name] = toOpenCodeServer(server.server);
        await this.saveMcpMap(config, mcp);
    }
    async removeServer(server) {
        const config = await readJsonFile(this.configPath, {});
        const mcp = this.getMcpMap(config);
        if (!mcp[server.name]) {
            return;
        }
        delete mcp[server.name];
        await this.saveMcpMap(config, mcp);
    }
}
