package org.matrix.socket;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.commons.beanutils.BeanUtils;
import org.matrix.actuators.datasource.IDataSourceService;
import org.matrix.actuators.sql.SqlExpActuator;
import org.matrix.actuators.usecase.CaseActuator;
import org.matrix.database.entity.TestCase;
import org.matrix.database.entity.TestCaseListDataBto;
import org.matrix.database.entity.TestData;
import org.matrix.database.entity.TestJob;
import org.matrix.database.service.ITestCaseService;
import org.matrix.database.service.ITestDataService;
import org.matrix.database.service.ITestJobService;
import org.matrix.exception.GlobalException;
import org.matrix.socket.enums.SocketType;
import org.matrix.socket.pool.MonitorSocketPool;
import org.matrix.socket.vo.CaseExecuteVo;
import org.matrix.socket.vo.ExecuteMonitorVo;
import org.matrix.socket.vo.SocketVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
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.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * webSocket处理 调用和执行的日志发送
 *
 * @author huangxiahao
 */
@Component
public class ExecutionSocketHandler extends TextWebSocketHandler {

    public static final MonitorSocketPool EXECUTE_MONITOR_SOCKET_POOL = new MonitorSocketPool();

    final CaseActuator caseActuator;
    final ITestDataService testDataService;
    final ITestJobService testJobService;
    final ITestCaseService testCaseService;
    final SqlExpActuator sqlExpActuator;
    final JdbcTemplate jdbcTemplate;
    final IDataSourceService dataSourceService;

    public ExecutionSocketHandler(CaseActuator caseActuator, ITestDataService testDataService, ITestJobService testJobService, ITestCaseService testCaseService, SqlExpActuator sqlExpActuator, JdbcTemplate jdbcTemplate, IDataSourceService dataSourceService) {
        this.caseActuator = caseActuator;
        this.testDataService = testDataService;
        this.testJobService = testJobService;
        this.testCaseService = testCaseService;
        this.sqlExpActuator = sqlExpActuator;
        this.jdbcTemplate = jdbcTemplate;
        this.dataSourceService = dataSourceService;
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        //检验客户端是否进行测试用例调试
        try {
            SocketVo socketVo = JSON.parseObject(payload, SocketVo.class);
            //如果客户端发送测试用例调试命令，则进行测试用例的执行
            if (socketVo != null && socketVo.getSocketType() != null) {
                if (SocketType.TEST_CASE_EXECUTE.equals(socketVo.getSocketType())) {
                    CaseExecuteVo caseExecuteVo = JSON.parseObject(payload, CaseExecuteVo.class);
                    caseActuator.runTestCase(session, caseExecuteVo);
                } else if (SocketType.TEST_JOB_EXECUTE.equals(socketVo.getSocketType())) {
                    CaseExecuteVo caseExecuteVo = JSON.parseObject(payload, CaseExecuteVo.class);
                    TestJob byId = testJobService.getById(caseExecuteVo.getJobId());
                    String sqlStatement = byId.getSqlStatement();
                    dataSourceService.switchMainDataSource();
                    List<Map<String, Object>> list = jdbcTemplate.queryForList(sqlStatement);
                    List<TestCase> testCaseList = new ArrayList<>();
                    for (Map<String, Object> objectMap : list) {
                        TestCase testCase = BeanUtil.mapToBean(objectMap,TestCase.class,false);
                        testCaseList.add(testCase);
                    }
                    for (TestCase testCase : testCaseList) {
                        List<TestData> testDataList = testDataService.list(Wrappers.lambdaQuery(TestData.class).eq(TestData::getTestCaseId, testCase.getId()));
                        TestCaseListDataBto  testCaseListDataBto = new TestCaseListDataBto();
                        testCaseListDataBto.setTestCase(testCase);
                        testCaseListDataBto.setTestDataList(testDataList);
                        caseExecuteVo.getTestCaseListDataBtoList().add(testCaseListDataBto);
                    }
                    if (testCaseList.size()>0){
                        caseExecuteVo.setProjectId(testCaseList.get(0).getProjectId());
                    }
                    caseActuator.runTestCase(session, caseExecuteVo);
                } else if (SocketType.TEST_CASE_MONITOR.equals(socketVo.getSocketType())) {
                    ExecuteMonitorVo caseExecuteVo = JSON.parseObject(payload, ExecuteMonitorVo.class);
                    EXECUTE_MONITOR_SOCKET_POOL.add(caseExecuteVo.getUniqueKey(), session);
                } else {
                    throw new GlobalException("入参不符合规定");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            session.sendMessage(new TextMessage(e.getMessage()));
        }
    }


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


}
