package com.qqchen.deploy.backend.framework.ssh.websocket;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qqchen.deploy.backend.framework.enums.SSHMessageType;
import com.qqchen.deploy.backend.framework.enums.SSHStatusEnum;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Map;

/**
 * SSH WebSocket消息（Framework层）
 * 
 * 统一的消息格式规范：
 * {
 *   "type": "output" | "input" | "status" | "error",
 *   "data": "消息内容（字符串）",
 *   "timestamp": 1733475005408,
 *   "metadata": { ... }  // 可选
 * }
 */
@Data
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SSHWebSocketMessage {
    
    /**
     * 消息类型
     */
    private SSHMessageType type;
    
    /**
     * 消息内容（可以是字符串或对象）
     * 
     * 字符串类型（后端→前端）：
     * - type=OUTPUT: 终端输出内容
     * - type=STATUS: 状态值（connecting/connected/reconnecting/disconnected/error）
     * - type=ERROR: 错误描述信息
     * 
     * 字符串类型（前端→后端）：
     * - type=INPUT: 用户输入内容
     * 
     * 对象类型（前端→后端）：
     * - type=RESIZE: {"request": {"rows": 40, "cols": 150}}
     * 
     * 对象类型（后端→前端，预留）：
     * - 未来可能的response: {"response": {...}}
     */
    private Object data;
    
    /**
     * 消息时间戳（Unix毫秒）
     * 服务端自动生成
     */
    private Long timestamp;
    
    /**
     * 可选元数据
     * 
     * 用于特殊场景的扩展字段，通常为null
     */
    private Map<String, Object> metadata;
    
    /**
     * 构造函数（自动填充时间戳）
     */
    public SSHWebSocketMessage(SSHMessageType type, Object data) {
        this.type = type;
        this.data = data;
        this.timestamp = System.currentTimeMillis();
    }
    
    /**
     * 创建OUTPUT消息
     * 
     * @param data 终端输出内容
     */
    public static SSHWebSocketMessage output(String data) {
        return new SSHWebSocketMessage(SSHMessageType.OUTPUT, data);
    }
    
    /**
     * 创建STATUS消息
     * 
     * @param status 状态枚举
     */
    public static SSHWebSocketMessage status(SSHStatusEnum status) {
        return new SSHWebSocketMessage(SSHMessageType.STATUS, status.name().toLowerCase());
    }
    
    /**
     * 创建ERROR消息
     * 
     * @param message 错误描述
     */
    public static SSHWebSocketMessage error(String message) {
        return new SSHWebSocketMessage(SSHMessageType.ERROR, message);
    }
    
    /**
     * 创建INPUT消息（前端发送，后端解析用）
     * 
     * @param data 用户输入内容
     */
    public static SSHWebSocketMessage input(String data) {
        return new SSHWebSocketMessage(SSHMessageType.INPUT, data);
    }
    
    /**
     * 从消息中提取request对象（强类型转换）
     * 
     * @param requestClass 请求类型
     * @return 请求对象，如果解析失败返回null
     */
    @SuppressWarnings("unchecked")
    public <T> T getRequest(Class<T> requestClass) {
        try {
            if (data instanceof Map) {
                Map<String, Object> dataMap = (Map<String, Object>) data;
                Object requestObj = dataMap.get("request");
                
                if (requestObj != null) {
                    // 如果已经是目标类型，直接返回
                    if (requestClass.isInstance(requestObj)) {
                        return (T) requestObj;
                    }
                    // 否则使用ObjectMapper转换（Map -> POJO）
                    ObjectMapper mapper = new ObjectMapper();
                    T result = mapper.convertValue(requestObj, requestClass);
                    
                    // 自动填充type字段（如果request中没有type，使用外层的type）
                    if (result instanceof com.qqchen.deploy.backend.framework.ssh.websocket.request.SSHBaseRequest) {
                        com.qqchen.deploy.backend.framework.ssh.websocket.request.SSHBaseRequest baseRequest = 
                            (com.qqchen.deploy.backend.framework.ssh.websocket.request.SSHBaseRequest) result;
                        if (baseRequest.getType() == null && this.type != null) {
                            baseRequest.setType(this.type);
                        }
                    }
                    
                    return result;
                }
            }
        } catch (Exception e) {
            // 转换失败，返回null
        }
        return null;
    }
    
    /**
     * 检查data是否包含request
     */
    public boolean hasRequest() {
        return data instanceof Map && ((Map<?, ?>) data).containsKey("request");
    }
}
