import { MessagePair, MessagePairRegistry } from '../../App/Msg/MessagePairBase';
import { DefaultNetConfig, NetConfig, NetProtocolType } from './NetConfig';
import { NetEvent } from './NetEvent';
import { ClientConfig, PlatformAdapter } from './PlatformAdapter';
import { INetClient } from './WebSocketClient';

/**
 * 网络管理器单例
 * 负责管理网络连接和消息通信
 * 支持 HTTP 和 WebSocket 两种协议
 */
export class NetManager {
    private static _instance: NetManager | null = null;

    /** TSRPC Client 实例 (HttpClient 或 WsClient) */
    private _client: INetClient | null = null;

    /** 是否已连接 */
    private _isConnected: boolean = false;

    /** 网络配置 */
    private _config: NetConfig | null = null;

    /** 重连计数 */
    private _reconnectCount: number = 0;

    /** 重连定时器 */
    private _reconnectTimer: any = null;

    /** 事件监听器 */
    private _eventListeners: Map<string, Function[]> = new Map();

    private constructor() { }

    /**
     * 获取单例实例
     */
    static getInstance(): NetManager {
        if (!this._instance) {
            this._instance = new NetManager();
        }
        return this._instance;
    }

    /**
     * 设置服务协议 (必须在 init 之前调用)
     * @param serviceProto 从 shared 目录导入的协议定义
     */
    setServiceProto(serviceProto: any): void {
        PlatformAdapter.setServiceProto(serviceProto);
    }

    /**
     * 初始化网络管理器
     * @param config 网络配置
     */
    init(config: NetConfig): void {
        this._config = {
            ...DefaultNetConfig,
            ...config
        } as NetConfig;

        console.log('[NetManager] Initialized with config:', this._config);
        console.log('[NetManager] Protocol:', this._config.protocolType);
        console.log('[NetManager] Platform:', PlatformAdapter.getPlatformInfo());
    }

    /**
     * 连接服务器
     */
    async connect(): Promise<boolean> {
        try {
            if (!this._config) {
                console.error('[NetManager] Config not set, please call init() first');
                return false;
            }

            console.log('[NetManager] Connecting to server:', this._config.serverUrl);

            // 创建客户端配置
            const clientConfig: ClientConfig = {
                server: this._config.serverUrl,
                protocolType: this._config.protocolType,
                json: this._config.json,
                timeout: this._config.timeout,
            };

            // 根据平台和协议类型创建对应的客户端
            this._client = PlatformAdapter.createClient(clientConfig);

            // 如果是 WebSocket 客户端，需要显式连接
            if (this._config.protocolType === NetProtocolType.WebSocket && this._client.connect) {
                this.emit(NetEvent.Connecting);

                const result = await this._client.connect();
                if (!result.isSucc) {
                    console.error('[NetManager] WebSocket connection failed:', result.errMsg);
                    this.emit(NetEvent.Error, result.errMsg);

                    // 尝试重连
                    if (this._config.autoReconnect) {
                        this.scheduleReconnect();
                    }
                    return false;
                }
            }

            this._isConnected = true;
            this._reconnectCount = 0;

            this.emit(NetEvent.Connected);
            console.log('[NetManager] Connected successfully');
            return true;
        } catch (error) {
            console.error('[NetManager] Connection failed:', error);
            this.emit(NetEvent.Error, error);

            // 尝试重连
            if (this._config?.autoReconnect) {
                this.scheduleReconnect();
            }

            return false;
        }
    }

    /**
     * 断开连接
     */
    disconnect(): void {
        if (!this._isConnected || !this._client) {
            return;
        }

        console.log('[NetManager] Disconnecting...');

        // 清除重连定时器
        if (this._reconnectTimer) {
            clearTimeout(this._reconnectTimer);
            this._reconnectTimer = null;
        }

        // 如果是 WebSocket 客户端，调用断开连接方法
        if (this._client.disconnect) {
            this._client.disconnect();
        }

        this._isConnected = false;
        this._client = null;

        this.emit(NetEvent.Disconnected);
        console.log('[NetManager] Disconnected');
    }

    /**
     * 调用 API
     * @param apiName API 名称
     * @param req 请求参数
     */
    async callApi<Req, Res>(apiName: string, req: Req): Promise<Res | null> {
        if (!this._isConnected || !this._client) {
            console.error('[NetManager] Not connected');
            return null;
        }

        try {
            console.log(`[NetManager] Calling API: ${apiName}`, req);

            const result = await this._client.callApi(apiName, req);

            if (result.isSucc) {
                console.log(`[NetManager] API ${apiName} success:`, result.res);
                return result.res as Res;
            } else {
                console.error(`[NetManager] API ${apiName} failed:`, result.err);
                return null;
            }
        } catch (error) {
            console.error(`[NetManager] API ${apiName} error:`, error);
            this.emit(NetEvent.Error, error);
            return null;
        }
    }

    /**
     * 监听消息 (仅支持 WebSocket)
     * @param msgName 消息名称
     * @param handler 处理函数
     */
    listenMsg(msgName: string, handler: Function): void {
        if (!this._client) {
            console.error('[NetManager] Client not initialized');
            return;
        }

        if (!this._client.listenMsg) {
            console.warn('[NetManager] Message listening not supported for HTTP client');
            return;
        }

        console.log(`[NetManager] Listening message: ${msgName}`);
        this._client.listenMsg(msgName, handler);
    }

    /**
     * 取消监听消息 (仅支持 WebSocket)
     * @param msgName 消息名称
     * @param handler 处理函数(可选,不传则取消所有该消息的监听)
     */
    unlistenMsg(msgName: string, handler?: Function): void {
        if (!this._client) {
            console.error('[NetManager] Client not initialized');
            return;
        }

        if (!this._client.unlistenMsg) {
            console.warn('[NetManager] Message listening not supported for HTTP client');
            return;
        }

        console.log(`[NetManager] Unlisten message: ${msgName}`);
        this._client.unlistenMsg(msgName, handler);
    }

    /**
     * 发送消息并等待响应 (基于消息对系统)
     * @param messagePair 消息对实例
     * @param requestData 请求消息内容
     * @returns Promise<响应消息>
     */
    async callMsg<TReq, TRes>(messagePair: MessagePair<TReq, TRes>, requestData: TReq): Promise<TRes | null> {
        if (!this._isConnected || !this._client) {
            console.error('[NetManager] Not connected');
            return null;
        }

        const requestName = messagePair.requestName;
        const responseName = messagePair.responseName;

        // 验证请求消息格式
        if (!messagePair.isValidRequest(requestData)) {
            console.error(`[NetManager] Invalid request data for ${requestName}:`, requestData);
            return null;
        }

        console.log(`[NetManager] Calling message: ${requestName} -> ${responseName}`, requestData);

        return new Promise<TRes | null>((resolve, reject) => {
            // 创建一次性响应处理器
            const responseHandler = (response: TRes) => {
                // 验证响应消息格式
                if (!messagePair.isValidResponse(response)) {
                    return;
                }

                // 取消监听
                this.unlistenMsg(responseName, responseHandler);
                // 返回响应
                console.log(`[NetManager] Received response for ${requestName}:`, response);
                resolve(response);
            };

            // 监听响应
            this.listenMsg(responseName, responseHandler);

            // 发送请求消息
            this.sendMsg(requestName, requestData);

            // 设置超时处理
            const timeout = this._config?.timeout || 30000;
            setTimeout(() => {
                this.unlistenMsg(responseName, responseHandler);
                console.error(`[NetManager] Request timeout for ${requestName}`);
                resolve(null);
            }, timeout);
        });
    }

    /**
     * 发送消息 (仅支持 WebSocket)
     * @param msgName 消息名称
     * @param msg 消息内容
     */
    sendMsg(msgName: string, msg: any): void {
        if (!this._isConnected || !this._client) {
            console.error('[NetManager] Not connected');
            return;
        }

        if (!this._client.sendMsg) {
            console.warn('[NetManager] Message sending not supported for HTTP client');
            return;
        }

        console.log(`[NetManager] Sending message: ${msgName}`, msg);
        this._client.sendMsg(msgName, msg);
    }

    /**
     * 安排重连
     */
    private scheduleReconnect(): void {
        if (!this._config) {
            return;
        }

        if (this._reconnectCount >= (this._config.maxReconnectTimes || 5)) {
            console.error('[NetManager] Max reconnect times reached');
            this.emit(NetEvent.ReconnectFailed);
            return;
        }

        this._reconnectCount++;
        console.log(`[NetManager] Scheduling reconnect (${this._reconnectCount}/${this._config.maxReconnectTimes})...`);

        this.emit(NetEvent.Reconnecting, this._reconnectCount);

        this._reconnectTimer = setTimeout(() => {
            this.reconnect();
        }, this._config.reconnectInterval || 3000);
    }

    /**
     * 重新连接
     */
    private async reconnect(): Promise<void> {
        console.log('[NetManager] Reconnecting...');

        const success = await this.connect();

        if (success) {
            this.emit(NetEvent.ReconnectSuccess);
        } else if (this._config?.autoReconnect) {
            this.scheduleReconnect();
        }
    }

    /**
     * 监听网络事件
     * @param event 事件名称
     * @param callback 回调函数
     */
    on(event: NetEvent, callback: Function): void {
        if (!this._eventListeners.has(event)) {
            this._eventListeners.set(event, []);
        }
        this._eventListeners.get(event)!.push(callback);
    }

    /**
     * 取消监听网络事件
     * @param event 事件名称
     * @param callback 回调函数
     */
    off(event: NetEvent, callback: Function): void {
        const listeners = this._eventListeners.get(event);
        if (listeners) {
            const index = listeners.indexOf(callback);
            if (index > -1) {
                listeners.splice(index, 1);
            }
        }
    }

    /**
     * 触发事件
     * @param event 事件名称
     * @param args 事件参数
     */
    private emit(event: NetEvent, ...args: any[]): void {
        const listeners = this._eventListeners.get(event);
        if (listeners) {
            listeners.forEach(callback => {
                try {
                    callback(...args);
                } catch (error) {
                    console.error('[NetManager] Event callback error:', error);
                }
            });
        }
    }

    /**
     * 获取连接状态
     */
    get isConnected(): boolean {
        return this._isConnected;
    }

    /**
     * 获取客户端实例
     */
    get client(): INetClient | null {
        return this._client;
    }

    /**
     * 获取协议类型
     */
    get protocolType(): NetProtocolType | undefined {
        return this._config?.protocolType;
    }

    /**
     * 判断是否为 WebSocket 连接
     */
    get isWebSocket(): boolean {
        return this._config?.protocolType === NetProtocolType.WebSocket;
    }

    /**
     * 判断是否为 HTTP 连接
     */
    get isHttp(): boolean {
        return this._config?.protocolType === NetProtocolType.Http;
    }

    /**
     * 获取所有已注册的消息对信息
     * @returns 消息对列表
     */
    getMessagePairs(): { requestName: string; responseName: string }[] {
        const registry = MessagePairRegistry.getInstance();
        return registry.getAllPairs().map(pair => ({
            requestName: pair.requestName,
            responseName: pair.responseName
        }));
    }
}

