package com.lemon.cases;

import cn.hutool.core.lang.UUID;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Maps;
import com.lemon.pojo.Case;
import com.lemon.pojo.TestRecord;
import com.lemon.testng.WebSocketManager;
import com.lemon.utils.ExcelUtils;
import com.pcloud.llm.cockpit.api.domain.dto.request.WorkflowRequestBody;
import com.pcloud.llm.cockpit.api.domain.dto.response.CompletionResponse;
import org.apache.http.client.utils.DateUtils;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static com.lemon.utils.Robot.sendAlarm;

public class changjiangzuoyeserveCase extends BaseCase {

    private WebSocketManager webSocketManager;


    //excel用例路径 todo  此处需要根据具体书籍进行更换
    public static final String EXCEL_PATH = "src/test/resources/changjiangcase.xls";

    private static final String ramdonUserId = UUID.randomUUID().toString();

    private String caseTraceId;

    @BeforeClass()
    public void setup() throws URISyntaxException {
        webSocketManager = new WebSocketManager();
        webSocketManager.connect();
        // 清空所有共享变量
        ExcelUtils.wbdList.clear();
        ExcelUtils.caseList.clear();
        ExcelUtils.parameterList.clear();
        ExcelUtils.apiList.clear();
        webSocketManager.scheduler.scheduleAtFixedRate(() -> {
            if (webSocketManager.webSocketClient.isOpen()) {
                // todo  此处需要根据具体书籍进行更换
                String heartbeatMessage = "{\"event\":0,\"sendType\":0,\"userId\":\"33624445\",\"officialAccountsId\":23,\"messageBody\":\"\",\"origin\":\"WEB_H5\",\"bookId\":\"12623004\"}";
                webSocketManager.webSocketClient.send(heartbeatMessage);
                log.info("发送心跳消息: " + heartbeatMessage);
            }
        }, 1, 5, TimeUnit.SECONDS);
    }


    @Test(dataProvider = "data1", priority = 1, description = "接收event-3响应")
    public void testSendEvent2AndReceiveEvent3(Case cas) {
        try {
            // 重置参数
            webSocketManager.event5Messages = new ArrayList<>();

            caseTraceId = UUID.randomUUID().toString();
            log.info(caseTraceId + caseTraceId + "本次执行的case是：" + JSONUtil.toJsonStr(cas) + "caseTraceId是" + caseTraceId);
            webSocketManager.messageCount = cas.getMessageCount();
            // 设置 latch，等待服务端 event-3 响应
            webSocketManager.latch4Event3 = new CountDownLatch(1);
            // 定义 requestId，发送 event-2 消息时使用，并在接收 event-3 时验证
            String event2Message = cas.getParams();
            log.info(caseTraceId + "发送event2的消息是" + event2Message);
            JSONObject sendJson = JSONUtil.parseObj(event2Message);
            webSocketManager.sendMessage(event2Message);
            webSocketManager.expectedRequestId = sendJson.getStr("requestId");
            log.info(caseTraceId + "expectedRequestId是" + webSocketManager.expectedRequestId);
            // 等待最多 10 秒
            boolean event3Received = webSocketManager.latch4Event3.await(60, TimeUnit.SECONDS);
            Assert.assertTrue(event3Received, "未在规定时间内收到 event-3 响应");
            log.info(caseTraceId + "收到的msgRemoteId是: " + webSocketManager.msgRemoteId);
            // 验证 msgRemoteId 非空
            Assert.assertNotNull(webSocketManager.msgRemoteId, "msgRemoteId 不应为空");
            // 验证 event-3 的 requestId 是否匹配
            log.info(caseTraceId + "receivedRequestId 是: " + webSocketManager.receivedRequestId + "expectedRequestId 是: " + webSocketManager.expectedRequestId);
            Assert.assertEquals(webSocketManager.receivedRequestId, webSocketManager.expectedRequestId, "收到的 requestId 不匹配");
        } catch (Exception e) {
            log.info(caseTraceId + "testSendEvent2AndReceiveEvent3,WebSocket出错: " + e.getMessage());
        }

        // 接收event-5响应
        try {
            // 设置 latch，等待服务端 event-5 响应
            webSocketManager.latch4Event5 = new CountDownLatch(webSocketManager.messageCount);
            // 等待并验证 event-5 消息
            boolean event5Received = webSocketManager.latch4Event5.await(120, TimeUnit.SECONDS);
            Assert.assertTrue(event5Received, "未在规定时间内收到 event-5 响应");
            // 验证 event-5 消息的内容
            log.info(caseTraceId + "event5 收到的消息是: " + JSONUtil.toJsonStr(webSocketManager.event5Messages));
            Assert.assertNotNull(webSocketManager.event5Messages, "event-5 消息不应为空");
            addWBD(Integer.parseInt(cas.getId()), 6, JSONUtil.toJsonStr(webSocketManager.event5Messages));
            cas.setActualValue(JSONUtil.toJsonStr(webSocketManager.event5Messages));
            cas.setPass(cas.getExpectValue().equals(cas.getActualValue()) ? 1 : 0);
        } catch (Exception e) {
            log.info(caseTraceId + "testReceiveEvent5Responses,WebSocket出错: " + e.getMessage());
        } finally {
            // 同时将测试结果新增到数据库中
            TestRecord testRecord = new TestRecord();
            testRecord.setCaseId(Integer.valueOf(cas.getId()));
            testRecord.setCaseDesc(cas.getDesc());
            testRecord.setInquiry(cas.getParams());
            testRecord.setExpectContent(cas.getExpectValue());
            testRecord.setInputContent(cas.getParams());
            testRecord.setOutputContent(JSONUtil.toJsonStr(webSocketManager.event5Messages));
            testRecord.setState(cas.getPass());
            testRecord.setTestVersion(DateUtils.formatDate(new Date(), "yyyyMMdd HH:mm"));
            testRecord.setCreateTime(new Date());
            testRecord.setUpdateTime(new Date());
            testRecord.setIsDelete(0);
            // SqlUtils.insertTestRecord(testRecord);
            // 如果失败则发送消息提醒
            if (cas.getPass() == null || cas.getPass() == 0)
                sendAlarm(cas.getParams());
        }

    }


/*
    @Test(dataProvider = "data1", priority = 2, dependsOnMethods = "testSendEvent2AndReceiveEvent3", description = "接收event-5响应")
    public void testReceiveEvent5Responses(Case cas) {

    }
*/


    @AfterClass
    public void tearDown() {
        // 关闭连接
        webSocketManager.close();
        // 将执行结果发给模型进行判断用例是否通过
        List<Case> caseList4Excel = ExcelUtils.read(EXCEL_PATH, 0, Case.class);
        // 转换为只保留指定字段的 JSON 数组
        List<JSONObject> filteredList = new ArrayList<>();
        for (Case item : caseList4Excel) {
            // 构造一个只包含所需字段的 JSONObject
            JSONObject jsonObject = new JSONObject();
            jsonObject.putOpt("id", item.getId());
            jsonObject.putOpt("expectValue", item.getExpectValue());
            jsonObject.putOpt("actualValue", Optional.ofNullable(item.getActualValue()).orElse(""));
            filteredList.add(jsonObject);
        }
        // 转换为 JSON 字符串
        String jsonStr = JSONUtil.toJsonStr(filteredList);
        log.info(caseTraceId + "本次执行的测试结果是: " + jsonStr);
        //调用dify
        Map<String, Object> inputs = Maps.newHashMap();
        inputs.put("inquery", jsonStr);
        WorkflowRequestBody requestBody = WorkflowRequestBody.builder().user(ramdonUserId).inputs(inputs).build();
        log.info(caseTraceId + "调用dify请求参数：" + JSONUtil.toJsonStr(requestBody));
        String res = "";
        try {
            CompletionResponse aiTopicScience = webSocketManager.workflowsRunBlocking("ai_autotest", requestBody);
            Map<String, Object> outputs = aiTopicScience.getData().getOutputs();
            res = (String) outputs.get("result");
            res = res.replace("```json", "").replace("```", "");
            List<Case> resultList = JSONUtil.toList(res,Case.class);
            for (Case item : resultList) {
                addWBD(Integer.parseInt(item.getId()), 7, Optional.ofNullable(item.getPass()).map(String::valueOf).orElse(""));
            }
        } catch (Exception e) {
            log.warn("请求dify异常：{}" + e.getMessage());
        }
        log.info(caseTraceId + "dify返回的内容======>{}" + res);
        log.info("===================批量回写===================");
        ExcelUtils.batchWrite(EXCEL_PATH);
        log.info("===================项目结束===================");
    }

    @DataProvider(name = "data1")
    public Object[][] data1() {
        Object[][] totalCase = ExcelUtils.getTotalCase(EXCEL_PATH);
        return totalCase;
    }


}
