/**
 * SSH 连接策略
 * 职责：专门处理 SSH WebSocket 连接、消息协议、重连逻辑
 */

import { BaseConnectionStrategy, ConnectionConfig, ConnectionStatus } from './BaseConnectionStrategy';

export interface SSHConnectionConfig extends ConnectionConfig {
    type: 'ssh';
    serverId: string | number;
    token?: string;
}

interface TerminalReceiveMessage {
    type: 'output' | 'error' | 'status';
    data: string | { response?: { data?: string } };
}

/**
 * SSH 连接策略实现
 */
export class SSHConnectionStrategy extends BaseConnectionStrategy {
    private ws: WebSocket | null = null;
    private reconnectAttempts = 0;
    private reconnectTimer: NodeJS.Timeout | null = null

    constructor(private sshConfig: SSHConnectionConfig) {
        super(sshConfig);
    }


    /**
     * 建立 SSH WebSocket 连接
     */
    async connect(): Promise<void> {
        if (this.ws?.readyState === WebSocket.OPEN) {
            return;
        }

        this.notifyStatusChange('connecting');
        this.reconnectAttempts = 0;
        
        // 直接构建WebSocket URL（不使用sessionId）
        const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
        const wsUrl = `${protocol}//${window.location.host}/api/v1/server-ssh/connect/${this.sshConfig.serverId}?token=${this.sshConfig.token}`;
        
        await this.connectWebSocket(wsUrl);
    }
    
    /**
     * 建立WebSocket连接
     */
    private connectWebSocket(wsUrl: string): Promise<void> {
        return new Promise((resolve, reject) => {
            try {
                const ws = new WebSocket(wsUrl);
                this.ws = ws;
                let isResolved = false;

                ws.onopen = () => {
                    this.notifyStatusChange('connected');
                    this.reconnectAttempts = 0;
                    isResolved = true;
                    resolve();
                };

                ws.onmessage = (event) => {
                    this.handleMessage(event);
                };

                ws.onerror = (error) => {
                    console.error('[SSHConnectionStrategy] WebSocket error:', error);
                    // WebSocket错误时不立即设置状态，等待onclose处理
                };

                ws.onclose = () => {
                    console.log('[SSHConnectionStrategy] WebSocket closed, current status:', this.status);
                    
                    const wasConnecting = this.status === 'connecting';
                    
                    // 只有在已连接状态下关闭才尝试重连
                    if (this.status === 'connected' && this.config.autoReconnect) {
                        this.handleReconnect();
                    } else {
                        // 其他情况统一显示为"已断开连接"
                        this.notifyStatusChange('disconnected');
                        if (wasConnecting) {
                            // 初次连接失败
                            this.notifyError('无法连接到服务器');
                            if (!isResolved) {
                                reject(new Error('无法连接到服务器'));
                            }
                        }
                    }
                };
            } catch (error) {
                console.error('[SSHConnectionStrategy] Connection failed:', error);
                this.notifyStatusChange('error');
                reject(error);
            }
        });
    }

    /**
     * 断开连接
     */
    disconnect(): void {
        if (this.reconnectTimer) {
            clearTimeout(this.reconnectTimer);
            this.reconnectTimer = null;
        }

        if (this.ws) {
            this.ws.close();
            this.ws = null;
        }

        this.notifyStatusChange('disconnected');
    }

    /**
     * 发送输入命令
     */
    sendInput(data: string): void {
        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
            this.ws.send(JSON.stringify({
                type: 'input',
                data: {
                    request: {
                        type: 'input',
                        command: data
                    }
                }
            }));
        }
    }

    /**
     * 发送终端尺寸调整消息
     */
    resize(cols: number, rows: number): void {
        if (this.ws?.readyState === WebSocket.OPEN) {
            this.ws.send(JSON.stringify({
                type: 'resize',
                data: {
                    request: {
                        type: 'resize',
                        rows,
                        cols,
                    }
                }
            }));
        }
    }

    /**
     * 处理接收到的消息
     */
    private handleMessage(event: MessageEvent): void {
        try {
            const msg: TerminalReceiveMessage = JSON.parse(event.data);
            
            // 提取实际数据：处理后端 response 包装格式
            const actualData = typeof msg.data === 'string' 
                ? msg.data 
                : msg.data?.response?.data || '';

            switch (msg.type) {
                case 'output':
                    if (actualData) {
                        this.notifyMessage(actualData);
                    }
                    break;

                case 'error':
                    this.notifyError(actualData);
                    this.notifyStatusChange('error');
                    break;

                case 'status':
                    this.notifyStatusChange(actualData as ConnectionStatus);
                    break;
            }
        } catch (error) {
            console.error('[SSHConnectionStrategy] Failed to parse message:', error);
        }
    }

    /**
     * 处理重连逻辑
     */
    private handleReconnect(): void {
        const maxAttempts = this.config.maxReconnectAttempts ?? 5;
        const interval = this.config.reconnectInterval ?? 3000;

        if (this.reconnectAttempts >= maxAttempts) {
            this.notifyStatusChange('error');
            this.notifyError('连接断开，已达到最大重连次数');
            return;
        }

        this.reconnectAttempts++;
        this.notifyStatusChange('reconnecting');

        this.reconnectTimer = setTimeout(() => {
            this.connect().catch(error => {
                console.error('[SSHConnectionStrategy] Reconnect failed:', error);
            });
        }, interval);
    }

    /**
     * 清理资源
     */
    dispose(): void {
        this.disconnect();
        this.clearListeners();
    }
}
