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

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 lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;

import java.util.Map;

/**
 * Docker Container SSH WebSocket处理器（业务层）
 * 继承Framework的抽象Handler，只需实现5个方法
 * 
 * 示例实现：展示如何为Docker容器提供SSH终端能力
 */
@Slf4j
@Component
public class ContainerSSHWebSocketHandler extends AbstractSSHWebSocketHandler {
    
    // TODO: 注入Docker相关的Service
    // @Resource
    // private IDockerContainerService containerService;
    
    // @Resource
    // private IDockerAuditLogService dockerAuditLogService;
    
    private static final int MAX_SESSIONS_PER_CONTAINER = 3;
    
    /**
     * 构造函数（注入Framework依赖）
     */
    public ContainerSSHWebSocketHandler(
        SSHCommandServiceFactory sshCommandServiceFactory,
        SSHSessionManager sessionManager) {
        super(sshCommandServiceFactory, sessionManager);
    }

    // ========== 实现Framework要求的5个抽象方法 ==========
    
    /**
     * 1. 获取SSH连接目标（业务逻辑）
     */
    @Override
    protected SSHTarget getSSHTarget(WebSocketSession session) throws Exception {
        // 从URL提取containerId
        Long containerId = extractContainerId(session);
        if (containerId == null) {
            throw new IllegalArgumentException("无效的Container ID");
        }
        
        // TODO: 从数据库获取Container信息
        // DockerContainer container = containerService.findById(containerId);
        // if (container == null) {
        //     throw new IllegalArgumentException("容器不存在: " + containerId);
        // }
        
        // 构建SSH目标
        SSHTarget target = new SSHTarget();
        target.setTargetType(SSHTargetType.CONTAINER);
        
        // TODO: 从Docker API获取容器的SSH信息
        // Docker容器通常通过宿主机SSH + docker exec
        // target.setHost(container.getHostIp());
        // target.setPort(container.getSshPort());
        // target.setUsername(container.getUsername());
        // target.setAuthType(container.getAuthType());
        // target.setPassword(container.getPassword());
        // target.setOsType(container.getOsType());
        
        // 示例配置
        target.setHost("docker-host-ip");
        target.setPort(22);
        target.setUsername("docker-user");
        target.setMetadata(containerId);  // 保存containerId供后续使用
        
        return target;
    }

    /**
     * 2. 权限验证（业务逻辑）
     */
    @Override
    protected boolean checkPermission(Long userId, SSHTarget target) {
        // TODO: 实现Docker容器权限验证
        // Long containerId = (Long) target.getMetadata();
        // return dockerPermissionService.hasPermission(userId, containerId);
        
        log.warn("Docker容器权限验证尚未实现，默认允许所有用户访问");
        return true;
    }

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

    /**
     * 4. 获取WebSocket路径模式
     */
    @Override
    protected String getPathPattern() {
        return "/api/v1/docker-container-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 containerId = (Long) target.getMetadata();
        
        switch (event) {
            case AFTER_CONNECT:
                // 创建Docker审计日志
                try {
                    Long userId = eventData.getUserId();
                    log.info("Docker容器连接审计: sessionId={}, containerId={}, userId={}", 
                        sessionId, containerId, userId);
                    // TODO: dockerAuditLogService.createAuditLog(...)
                } catch (Exception e) {
                    log.error("创建Docker审计日志失败: sessionId={}", sessionId, e);
                }
                break;
                
            case AFTER_DISCONNECT:
                // 关闭Docker审计日志
                log.info("Docker容器断开连接: sessionId={}, containerId={}", sessionId, containerId);
                // TODO: dockerAuditLogService.closeAuditLog(...)
                break;
                
            case ON_COMMAND:
                // 记录命令（可选）
                String command = eventData.getCommand();
                log.debug("Docker容器命令: sessionId={}, command={}", sessionId, command);
                // TODO: dockerAuditLogService.recordCommand(...)
                break;
                
            case ON_ERROR:
                // 记录错误
                String error = eventData.getErrorMessage();
                log.error("Docker容器连接错误: sessionId={}, error={}", sessionId, error);
                // TODO: dockerAuditLogService.closeAuditLog(sessionId, "FAILED", error);
                break;
                
            case BEFORE_SHUTDOWN:
                // 优雅下线
                String reason = eventData.getDisconnectReason();
                log.info("Docker容器优雅下线: sessionId={}, reason={}", sessionId, reason);
                // TODO: dockerAuditLogService.closeAuditLog(sessionId, "SERVER_SHUTDOWN", reason);
                break;
        }
    }

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