import { useMessageBridge } from '@/api/message-bridge';
import { reactive } from 'vue';
import { pinkLog } from '../setting/util';
import { ElMessage } from 'element-plus';
import { ILaunchSigature } from '@/hook/type';

export const connectionMethods = reactive({
    current: 'STDIO',
    data: [
        {
            value: 'STDIO',
            label: 'STDIO'
        },
        {
            value: 'SSE',
            label: 'SSE'
        }
    ]
});

export const connectionArgs = reactive({
    commandString: '',
    cwd: '',
    oauth: '',
    urlString: ''
});

export interface EnvItem {
    key: string
    value: string
}

export interface IConnectionEnv {
    data: EnvItem[]
    newKey: string
    newValue: string
}

export const connectionEnv = reactive<IConnectionEnv>({
    data: [],
    newKey: '',
    newValue: ''
});

export function makeEnv() {
    const env = {} as Record<string, string>;
    connectionEnv.data.forEach(item => {
        env[item.key] = item.value;
    });
    return env;
}


// 定义连接类型
type ConnectionType = 'STDIO' | 'SSE';

// 定义命令行参数接口
export interface MCPOptions {
    connectionType: ConnectionType;
    // STDIO 特定选项
    command?: string;
    args?: string[];
    cwd?: string;
    env?: Record<string, string>;
    // SSE 特定选项
    url?: string;
    // 通用客户端选项
    clientName?: string;
    clientVersion?: string;
}

export function doConnect() {
    let connectOption: MCPOptions;
    const bridge = useMessageBridge();
    const env = makeEnv();

    return new Promise((resolve, reject) => {
        // 监听 connect
        bridge.addCommandListener('connect', async data => {
            const { code, msg } = data;
            connectionResult.success = (code === 200);

            if (code === 200) {
                const res = await getServerVersion() as { name: string, version: string };
                connectionResult.serverInfo.name = res.name || '';
                connectionResult.serverInfo.version = res.version || '';
                connectionResult.logString.push({
                    type: 'info',
                    message: msg
                });

            } else {
                ElMessage({
                    type: 'error',
                    message: msg
                });
                connectionResult.logString.push({
                    type: 'error',
                    message: msg
                });
            }

            resolve(void 0);
        }, { once: true });

        if (connectionMethods.current === 'STDIO') {

            if (connectionArgs.commandString.length === 0) {
                return;
            }

            const commandComponents = connectionArgs.commandString.split(/\s+/g);
            const command = commandComponents[0];
            commandComponents.shift();

            connectOption = {
                connectionType: 'STDIO',
                command: command,
                cwd: connectionArgs.cwd,
                args: commandComponents,
                env: env,
                clientName: 'openmcp.connect.stdio',
                clientVersion: '0.0.1'
            }

        } else {
            const url = connectionArgs.urlString;

            if (url.length === 0) {
                return;
            }

            connectOption = {
                connectionType: 'SSE',
                url: url,
                env: env,
                clientName: 'openmcp.connect.sse',
                clientVersion: '0.0.1'
            }
        }

        bridge.postMessage({
            command: 'connect',
            data: connectOption
        });
    });
}

/**
 * @description vscode 中初始化启动
 */
export async function launchConnect(option: { updateCommandString?: boolean } = {}) {
    // 本地开发只用 IPC 进行启动
    // 后续需要考虑到不同的连接方式

    const {
        updateCommandString = true
    } = option;

    connectionMethods.current = 'STDIO';

    pinkLog('请求启动参数');
    const connectionItem = await getLaunchSignature();

    if (connectionItem.type === 'stdio') {
        if (updateCommandString) {
            connectionArgs.commandString = connectionItem.commandString;
            connectionArgs.cwd = connectionItem.cwd;

            if (connectionArgs.commandString.length === 0) {
                return;
            }
        }
        
        await launchStdio();

    } else {
        if (updateCommandString) {
            connectionArgs.urlString = connectionItem.url;
            if (connectionArgs.urlString.length === 0) {
                return;
            }
        }

        await launchSSE();

    }
}

async function launchStdio() {
    const bridge = useMessageBridge();
    const env = makeEnv();

    return new Promise<void>((resolve, reject) => {
        // 监听 connect
        bridge.addCommandListener('connect', async data => {
            const { code, msg } = data;
            connectionResult.success = (code === 200);

            if (code === 200) {
                connectionResult.logString.push({
                    type: 'info',
                    message: msg
                });                

                const res = await getServerVersion() as { name: string, version: string };
                connectionResult.serverInfo.name = res.name || '';
                connectionResult.serverInfo.version = res.version || '';

                // 同步信息到 vscode
                const commandComponents = connectionArgs.commandString.split(/\s+/g);
                const command = commandComponents[0];
                commandComponents.shift();

                const clientStdioConnectionItem = {
                    serverInfo: connectionResult.serverInfo,
                    connectionType: 'STDIO',
                    name: 'openmcp.connect.stdio',
                    command: command,
                    args: commandComponents,
                    cwd: connectionArgs.cwd,
                    env
                };

                bridge.postMessage({
                    command: 'vscode/update-connection-sigature',
                    data: JSON.parse(JSON.stringify(clientStdioConnectionItem))
                });

            } else {
                connectionResult.logString.push({
                    type: 'error',
                    message: msg
                });

                ElMessage({
                    type: 'error',
                    message: msg
                });
            }

            resolve(void 0);
        }, { once: true });


        const commandComponents = connectionArgs.commandString.split(/\s+/g);
        const command = commandComponents[0];
        commandComponents.shift();

        const connectOption = {
            connectionType: 'STDIO',
            command: command,
            args: commandComponents,
            cwd: connectionArgs.cwd,
            clientName: 'openmcp.connect.stdio',
            clientVersion: '0.0.1',
            env
        };

        bridge.postMessage({
            command: 'connect',
            data: connectOption
        });
    });
}

async function launchSSE() {
    const bridge = useMessageBridge();
    const env = makeEnv();

    return new Promise<void>((resolve, reject) => {
        // 监听 connect
        bridge.addCommandListener('connect', async data => {
            const { code, msg } = data;
            connectionResult.success = (code === 200);

            if (code === 200) {
                connectionResult.logString.push({
                    type: 'info',
                    message: msg
                });

                const res = await getServerVersion() as { name: string, version: string };
                connectionResult.serverInfo.name = res.name || '';
                connectionResult.serverInfo.version = res.version || '';
                
                // 同步信息到 vscode
                const clientSseConnectionItem = {
                    serverInfo: connectionResult.serverInfo,
                    connectionType: 'SSE',
                    name: 'openmcp.connect.sse',
                    url: connectionArgs.urlString,
                    oauth: connectionArgs.oauth,
                    env: env
                };
                bridge.postMessage({
                    command: 'vscode/update-connection-sigature',
                    data: JSON.parse(JSON.stringify(clientSseConnectionItem))
                });

            } else {
                connectionResult.logString.push({
                    type: 'error',
                    message: msg
                });

                ElMessage({
                    type: 'error',
                    message: msg
                });
            }

            resolve(void 0);
        }, { once: true });

        const connectOption: MCPOptions = {
            connectionType: 'SSE',
            url: connectionArgs.urlString,
            clientName: 'openmcp.connect.sse',
            clientVersion: '0.0.1',
            env
        };

        bridge.postMessage({
            command: 'connect',
            data: connectOption
        });
    });
}



function getLaunchSignature() {
    return new Promise<ILaunchSigature>((resolve, reject) => {
        // 与 vscode 进行同步
        const bridge = useMessageBridge();

        bridge.addCommandListener('vscode/launch-signature', data => {
            pinkLog('收到启动参数');
            resolve(data.msg);

        }, { once: true });

        bridge.postMessage({
            command: 'vscode/launch-signature',
            data: {}
        });
    })
}

export function doReconnect() {
    // TODO: finish this
    console.log();
}

export const connectionResult = reactive<{
    success: boolean,
    logString: { type: 'info' | 'error' | 'warning', message: string }[],
    serverInfo: {
        name: string,
        version: string
    }
}>({
    success: false,
    logString: [],
    serverInfo: {
        name: '',
        version: ''
    }
});

export function getServerVersion() {
    return new Promise((resolve, reject) => {
        const bridge = useMessageBridge();
        bridge.addCommandListener('server/version', data => {
            if (data.code === 200) {
                resolve(data.msg);
            } else {
                reject(data.msg);
            }
        }, { once: true });

        bridge.postMessage({
            command: 'server/version',
        });
    });
}

export const envVarStatus = {
    launched: false
};