import { BaseServiceType } from 'tsrpc-browser';
import { NetEvent } from './NetEvent';

/**
 * WebSocket 连接状态
 */
export enum WsConnectionStatus {
    /** 已断开 */
    Disconnected = "disconnected",
    /** 连接中 */
    Connecting = "connecting",
    /** 已连接 */
    Connected = "connected",
    /** 连接失败 */
    Failed = "failed"
}

/**
 * WebSocket 客户端接口
 * 统一 HTTP 和 WebSocket 客户端的接口
 */
export interface INetClient<T extends BaseServiceType = any> {
    /** 调用API */
    callApi<Req, Res>(apiName: string, req: Req): Promise<{ isSucc: boolean; res?: Res; err?: any }>;

    /** 监听消息 (仅 WebSocket) */
    listenMsg?(msgName: string, handler: Function): void;

    /** 取消监听消息 (仅 WebSocket) */
    unlistenMsg?(msgName: string, handler?: Function): void;

    /** 发送消息 (仅 WebSocket) */
    sendMsg?(msgName: string, msg: any): void;

    /** 连接 (仅 WebSocket) */
    connect?(): Promise<{ isSucc: boolean; errMsg?: string }>;

    /** 断开连接 (仅 WebSocket) */
    disconnect?(): void;

    /** 获取连接状态 */
    status?: WsConnectionStatus;
}

/**
 * WebSocket 客户端包装器
 * 提供统一的接口和事件处理
 */
export class WebSocketClientWrapper<T extends BaseServiceType = any> implements INetClient<T> {
    private _wsClient: any = null;
    private _status: WsConnectionStatus = WsConnectionStatus.Disconnected;
    private _eventCallbacks: Map<string, Function[]> = new Map();

    constructor(wsClient: any) {
        this._wsClient = wsClient;
        this.setupEventHandlers();
    }

    /**
     * 设置事件处理器
     */
    private setupEventHandlers(): void {
        if (!this._wsClient) return;

        // 监听连接事件
        this._wsClient.flows.preConnectFlow.push((v: any) => {
            this._status = WsConnectionStatus.Connecting;
            this.emit(NetEvent.Connecting);
            return v;
        });

        this._wsClient.flows.postConnectFlow.push((v: any) => {
            if (v.isSucc) {
                this._status = WsConnectionStatus.Connected;
                this.emit(NetEvent.Connected);
            } else {
                this._status = WsConnectionStatus.Failed;
                this.emit(NetEvent.Error, v.errMsg);
            }
            return v;
        });

        // 监听断开连接事件
        this._wsClient.flows.postDisconnectFlow.push((v: any) => {
            this._status = WsConnectionStatus.Disconnected;
            this.emit(NetEvent.Disconnected);
            return v;
        });
    }

    /**
     * 连接服务器
     */
    async connect(): Promise<{ isSucc: boolean; errMsg?: string }> {
        try {
            this._status = WsConnectionStatus.Connecting;
            const result = await this._wsClient.connect();

            if (result.isSucc) {
                this._status = WsConnectionStatus.Connected;
            } else {
                this._status = WsConnectionStatus.Failed;
            }

            return result;
        } catch (error) {
            this._status = WsConnectionStatus.Failed;
            return {
                isSucc: false,
                errMsg: error instanceof Error ? error.message : String(error)
            };
        }
    }

    /**
     * 断开连接
     */
    disconnect(): void {
        if (this._wsClient && typeof this._wsClient.disconnect === 'function') {
            this._wsClient.disconnect();
        }
        this._status = WsConnectionStatus.Disconnected;
    }

    /**
     * 调用API
     */
    async callApi<Req, Res>(apiName: string, req: Req): Promise<{ isSucc: boolean; res?: Res; err?: any }> {
        if (this._status !== WsConnectionStatus.Connected) {
            return {
                isSucc: false,
                err: 'WebSocket not connected'
            };
        }

        try {
            return await this._wsClient.callApi(apiName, req);
        } catch (error) {
            return {
                isSucc: false,
                err: error
            };
        }
    }

    /**
     * 监听消息
     */
    listenMsg(msgName: string, handler: Function): void {
        if (this._wsClient && typeof this._wsClient.listenMsg === 'function') {
            this._wsClient.listenMsg(msgName, handler);
        }
    }

    /**
     * 取消监听消息
     */
    unlistenMsg(msgName: string, handler?: Function): void {
        if (this._wsClient && typeof this._wsClient.unlistenMsg === 'function') {
            this._wsClient.unlistenMsg(msgName, handler);
        }
    }

    /**
     * 发送消息
     */
    sendMsg(msgName: string, msg: any): void {
        if (this._status !== WsConnectionStatus.Connected) {
            console.warn('[WebSocketClient] Cannot send message: not connected');
            return;
        }

        if (this._wsClient && typeof this._wsClient.sendMsg === 'function') {
            this._wsClient.sendMsg(msgName, msg);
        }
    }

    /**
     * 注册事件监听器
     */
    on(event: NetEvent, callback: Function): void {
        if (!this._eventCallbacks.has(event)) {
            this._eventCallbacks.set(event, []);
        }
        this._eventCallbacks.get(event)!.push(callback);
    }

    /**
     * 取消事件监听器
     */
    off(event: NetEvent, callback: Function): void {
        const callbacks = this._eventCallbacks.get(event);
        if (callbacks) {
            const index = callbacks.indexOf(callback);
            if (index > -1) {
                callbacks.splice(index, 1);
            }
        }
    }

    /**
     * 触发事件
     */
    private emit(event: NetEvent, ...args: any[]): void {
        const callbacks = this._eventCallbacks.get(event);
        if (callbacks) {
            callbacks.forEach(callback => {
                try {
                    callback(...args);
                } catch (error) {
                    console.error('[WebSocketClient] Event callback error:', error);
                }
            });
        }
    }

    /**
     * 获取连接状态
     */
    get status(): WsConnectionStatus {
        return this._status;
    }

    /**
     * 判断是否已连接
     */
    get isConnected(): boolean {
        return this._status === WsConnectionStatus.Connected;
    }

    /**
     * 获取原始客户端实例
     */
    get rawClient(): any {
        return this._wsClient;
    }
}