package org.matrix.socket;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.commons.lang3.StringUtils;
import org.matrix.database.entity.ExecutionHistory;
import org.matrix.database.service.IExecutionHistoryService;
import org.matrix.database.vo.ExecutionHistoryVo;
import org.matrix.enums.ExecutionHistoryStatus;
import org.matrix.socket.enums.ExecuteStatusSendMessageType;
import org.matrix.socket.pool.MonitorSocketPool;
import org.matrix.socket.vo.ExecutionStatusMonitorVo;
import org.matrix.socket.vo.ExecutionStatusSendMessageVo;
import org.matrix.socket.vo.SocketResponseMessage;
import org.matrix.socket.vo.TestExecuteLog;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.List;

/**
 * webSocket处理
 * 订阅用例调试和测试任务执行的
 *
 * @author huangxiahao
 */
@Component
public class ExecutionStatusMonitorSocketHandler extends TextWebSocketHandler {

    public static final MonitorSocketPool EXECUTE_MONITOR_SOCKET_POOL = new MonitorSocketPool();

    private final IExecutionHistoryService executionHistoryService;

    public ExecutionStatusMonitorSocketHandler(IExecutionHistoryService executionHistoryService) {
        this.executionHistoryService = executionHistoryService;
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        super.handleTextMessage(session, message);
        String payload = message.getPayload();
        ExecutionStatusMonitorVo executionStatusMonitorVo = JSON.parseObject(payload, ExecutionStatusMonitorVo.class);
        if (executionStatusMonitorVo != null && executionStatusMonitorVo.getExecuteStatusMonitorType() != null) {
            switch (executionStatusMonitorVo.getExecuteStatusMonitorType()) {
                case DETAIL:
                    if (!StringUtils.isEmpty(executionStatusMonitorVo.getUniqueKey())&&executionStatusMonitorVo.getCaseId()!=null&&executionStatusMonitorVo.getDataId()!=null){
                        EXECUTE_MONITOR_SOCKET_POOL.add(String.format("%s.%s.%s.%s.%s",
                                executionStatusMonitorVo.getUserId(),
                                executionStatusMonitorVo.getJobId(),
                                executionStatusMonitorVo.getCaseId(),
                                executionStatusMonitorVo.getDataId(),
                                executionStatusMonitorVo.getUniqueKey()
                        ), session);
                    }
                    sendDetailCurrentStatus(
                            executionStatusMonitorVo.getUserId(),
                            executionStatusMonitorVo.getJobId(),
                            executionStatusMonitorVo.getCaseId(),
                            executionStatusMonitorVo.getDataId(),
                            executionStatusMonitorVo.getUniqueKey(),
                            null
                    );
                    break;
                default:
                    if (!StringUtils.isEmpty(executionStatusMonitorVo.getUniqueKey())){
                        EXECUTE_MONITOR_SOCKET_POOL.add(executionStatusMonitorVo.getUniqueKey(), session);
                        sendOverviewCurrentStatus(executionStatusMonitorVo.getUniqueKey());
                    }
            }
        } else {
            session.sendMessage(new TextMessage(SocketResponseMessage.fail("入参不符合规定")));
        }
    }

    public void sendOverviewCurrentStatus(String uniqueKey) throws IOException {
        //获取该数据当前执行状态
        IPage<ExecutionHistoryVo> page = executionHistoryService.pageExecutionHistoryVoByCaseIdAndJobId(null, null, uniqueKey, 1, 10);
        if (page.getRecords() != null && page.getRecords().size() > 0) {
            ExecutionHistoryStatus status = page.getRecords().get(0).getStatus();
            ExecutionStatusSendMessageVo sendMessageVo = new ExecutionStatusSendMessageVo(
                    uniqueKey,
                    null,
                    null,
                    null,
                    status,
                    ExecuteStatusSendMessageType.OVERVIEW
            );
            List<WebSocketSession> webSocketSessions = EXECUTE_MONITOR_SOCKET_POOL.get(uniqueKey);
            if (webSocketSessions!=null){
                for (WebSocketSession webSocketSession : webSocketSessions) {
                    webSocketSession.sendMessage(new TextMessage(SocketResponseMessage.success(JSONObject.toJSONString(sendMessageVo))));
                }
            }
        }
    }

    public void sendDetailCurrentStatus(Long userId,Long jobId,Long caseId,Long dataId,String uniqueKey,ExecutionHistoryStatus status) throws IOException {
        //获取该数据当前执行状态
        String key = String.format("%s.%s.%s.%s.%s",
                userId,
                jobId,
                caseId,
                dataId,
                uniqueKey
        );
        if (status==null){
            LambdaQueryWrapper<ExecutionHistory> eq = Wrappers.lambdaQuery(ExecutionHistory.class)
                    .eq(ExecutionHistory::getUserId, userId)
                    .eq(ExecutionHistory::getJobId, jobId)
                    .eq(ExecutionHistory::getCaseId, caseId)
                    .eq(ExecutionHistory::getDataId, dataId)
                    .eq(ExecutionHistory::getUniqueKey, uniqueKey);
             ExecutionHistory one = executionHistoryService.getOne(eq);
             if (one!=null){
                 status = one.getStatus();
             }
        }
        List<WebSocketSession> webSocketSessions = EXECUTE_MONITOR_SOCKET_POOL.get(key);
        ExecutionStatusSendMessageVo sendMessageVo = new ExecutionStatusSendMessageVo(
                uniqueKey,
                jobId,
                caseId,
                dataId,
                status,
                ExecuteStatusSendMessageType.Data
        );
        if (webSocketSessions!=null){
            for (WebSocketSession webSocketSession : webSocketSessions) {
                webSocketSession.sendMessage(new TextMessage(SocketResponseMessage.success(JSONObject.toJSONString(sendMessageVo))));
            }
        }

    }


    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
        EXECUTE_MONITOR_SOCKET_POOL.remove(session);
    }
}
