package com.qqchen.deploy.backend.deploy.handler;

import com.qqchen.deploy.backend.deploy.entity.Server;
import com.qqchen.deploy.backend.deploy.service.ISSHAuditLogService;
import com.qqchen.deploy.backend.deploy.service.IServerService;
import com.qqchen.deploy.backend.framework.enums.SSHEvent;
import com.qqchen.deploy.backend.framework.enums.SSHTargetType;
import com.qqchen.deploy.backend.framework.ssh.SSHCommandServiceFactory;
import com.qqchen.deploy.backend.framework.ssh.websocket.AbstractSSHWebSocketHandler;
import com.qqchen.deploy.backend.framework.ssh.websocket.SSHEventData;
import com.qqchen.deploy.backend.framework.ssh.websocket.SSHSessionManager;
import com.qqchen.deploy.backend.framework.ssh.websocket.SSHTarget;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;

import java.util.Map;

/**
 * Server SSH WebSocket处理器（业务层）
 * 继承Framework的抽象Handler，只需实现5个方法
 * 
 * 注意：asyncTaskExecutor 线程池由Framework自动注入，业务层无需关心
 */
@Slf4j
@Component
public class ServerSSHWebSocketHandler extends AbstractSSHWebSocketHandler {

    @Resource
    private IServerService serverService;
    
    @Resource
    private ISSHAuditLogService auditLogService;
    
    private static final int MAX_SESSIONS_PER_SERVER = 5;
    
    /**
     * 构造函数（注入业务依赖）
     * 
     * @param sshCommandServiceFactory SSH命令服务工厂
     * @param sessionManager SSH会话管理器
     */
    public ServerSSHWebSocketHandler(
        SSHCommandServiceFactory sshCommandServiceFactory,
        SSHSessionManager sessionManager) {
        super(sshCommandServiceFactory, sessionManager);
    }

    // ========== 实现Framework要求的5个抽象方法 ==========
    
    /**
     * 1. 获取SSH连接目标（业务逻辑）
     */
    @Override
    protected SSHTarget getSSHTarget(WebSocketSession session) throws Exception {
        // 从URL提取serverId
        Long serverId = extractServerId(session);
        if (serverId == null) {
            throw new IllegalArgumentException("无效的服务器ID");
        }
        
        // 获取服务器信息
        Server server = serverService.findEntityById(serverId);
        if (server == null) {
            throw new IllegalArgumentException("服务器不存在: " + serverId);
        }
        
        // 构建SSH目标
        SSHTarget target = new SSHTarget();
        target.setTargetType(SSHTargetType.SERVER);
        target.setHost(server.getHostIp());
        target.setPort(server.getSshPort());
        target.setUsername(server.getSshUser());
        target.setAuthType(server.getAuthType());
        target.setPassword(server.getSshPassword());
        target.setPrivateKey(server.getSshPrivateKey());
        target.setPassphrase(server.getSshPassphrase());
        target.setOsType(server.getOsType());
        target.setMetadata(serverId);  // 保存serverId供后续使用
        
        return target;
    }

    /**
     * 2. 权限验证（业务逻辑）
     */
    @Override
    protected boolean checkPermission(Long userId, SSHTarget target) {
        // TODO: 实现更细粒度的权限验证
        // 例如：检查用户是否有访问该服务器的权限
        return true;  // 暂时允许所有
    }

    /**
     * 3. 获取最大并发连接数
     */
    @Override
    protected int getMaxSessions() {
        return MAX_SESSIONS_PER_SERVER;
    }

    /**
     * 4. 获取WebSocket路径模式
     */
    @Override
    protected String getPathPattern() {
        return "/api/v1/server-ssh/connect/*";
    }

    /**
     * 5. 事件钩子（审计日志等业务逻辑）
     */
    @Override
    protected void onEvent(SSHEvent event, SSHEventData eventData) {
        String sessionId = eventData.getSessionId();
        SSHTarget target = eventData.getTarget();
        
        if (target == null) {
            log.warn("事件处理失败，target为null: event={}, sessionId={}", event, sessionId);
            return;
        }
        
        Long serverId = (Long) target.getMetadata();
        
        switch (event) {
            case AFTER_CONNECT:
                // 创建审计日志
                try {
                    Long userId = eventData.getUserId();
                    String clientIp = eventData.getClientIp();
                    String userAgent = eventData.getUserAgent();
                    Server server = serverService.findEntityById(serverId);
                    
                    if (server != null) {
                        Long auditLogId = auditLogService.createAuditLog(
                            userId, server, sessionId, clientIp, userAgent);
                        log.info("审计日志已创建: auditLogId={}, sessionId={}", auditLogId, sessionId);
                    }
                } catch (Exception e) {
                    log.error("创建审计日志失败: sessionId={}", sessionId, e);
                }
                break;
                
            case AFTER_DISCONNECT:
                // 关闭审计日志
                try {
                    auditLogService.closeAuditLog(sessionId, "SUCCESS", "正常断开");
                    log.info("审计日志已关闭: sessionId={}", sessionId);
                } catch (Exception e) {
                    log.error("关闭审计日志失败: sessionId={}", sessionId, e);
                }
                break;
                
            case ON_COMMAND:
                // 记录命令到审计日志
                try {
                    String command = eventData.getCommand();
                    if (command != null && command.length() > 0) {
                        auditLogService.recordCommand(sessionId, command);
                    }
                } catch (Exception e) {
                    log.error("记录命令失败: sessionId={}", sessionId, e);
                }
                break;
                
            case ON_ERROR:
                // 记录错误
                try {
                    String errorMessage = eventData.getErrorMessage();
                    auditLogService.closeAuditLog(sessionId, "FAILED", errorMessage);
                } catch (Exception e) {
                    log.error("记录错误失败: sessionId={}", sessionId, e);
                }
                break;
                
            case BEFORE_SHUTDOWN:
                // 优雅下线前处理审计日志（Framework统一调用）
                try {
                    String reason = eventData.getDisconnectReason();
                    auditLogService.closeAuditLog(sessionId, "SERVER_SHUTDOWN", reason);
                    log.info("审计日志已更新(优雅下线): sessionId={}", sessionId);
                } catch (Exception e) {
                    log.error("更新审计日志失败(优雅下线): sessionId={}", sessionId, e);
                }
                break;
        }
    }

    // ========== 辅助方法 ==========
    
    /**
     * 从WebSocket session URL中提取serverId
     */
    private Long extractServerId(WebSocketSession session) {
        try {
            String path = session.getUri().getPath();
            // /api/v1/server-ssh/connect/{serverId}
            String[] parts = path.split("/");
            if (parts.length > 0) {
                return Long.parseLong(parts[parts.length - 1]);
            }
        } catch (Exception e) {
            log.error("提取serverId失败", e);
        }
        return null;
    }
}
