package com.zehong.system.task;

import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.zehong.system.domain.TEquipmentInfo;
import com.zehong.system.modbus.util.Modbus4jUtils;
import com.zehong.system.service.ITEquipmentInfoService;
import com.zehong.system.service.websocket.AgingCabinetWebSocketHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * @author lenovo
 * @date 2025/6/9
 * @description 老化柜巡查 + 老化层断电检测
 */
@Component("agingCabinetInspectionAndPowerCheckTask")
public class AgingCabinetInspectionAndPowerCheckTask {

    private static final Logger log = LoggerFactory.getLogger(AgingCabinetInspectionAndPowerCheckTask.class);
    private final ExecutorService executor = Executors.newFixedThreadPool(10);
    @Resource
    private ITEquipmentInfoService tEquipmentInfoService;


    @Resource
    private AgingCabinetWebSocketHandler agingCabinetWebSocketHandler;
    /**
     * 五分钟一次
     * 1.老化柜、标定柜巡查
     * 2.老化层断电
     * 这种方式先注释掉
     //            for (TEquipmentInfo equipmentInfo : equipmentInfos) {
     //                Future<Map<Integer, Object>> future = executor.submit(new ModbusTcpTask(equipmentInfo, registerOffset));
     //                futures.add(future);
     //            }
     //            List<ModbusDeviceData> results = new ArrayList<>();
     //
     //            for (int i = 0; i < futures.size(); i++) {
     //                Map<Integer, Object> data = futures.get(i).get();
     //                ModbusDeviceData deviceData = new ModbusDeviceData();
     //                deviceData.setDeviceId(equipmentInfos.get(i).getfEquipmentId().toString());
     //                deviceData.setRegisterValues(data.entrySet().stream()
     //                        .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().toString())));
     //                results.add(deviceData);
     //            }
     */
    public void ryCheck() {

        List<String> type = new ArrayList<>();
        type.add("1");
        type.add("2");
        List<TEquipmentInfo> equipmentInfos = tEquipmentInfoService.selectTEquipmentList(type);

        try {
            if (equipmentInfos.size() == 0) {
                log.error("设备列表查询结果为空");
                return;
            }
            List<CompletableFuture<TEquipmentInfo>> futures = equipmentInfos.stream().map(equipmentInfo -> CompletableFuture.supplyAsync(() -> {
                ModbusMaster master = null;
                // 10 层
                List<Integer> registerOffsets = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
                try {
                    master = Modbus4jUtils.createModbusMaster(equipmentInfo.getfIp(), equipmentInfo.getfPort());
                    Map<Integer, Object> integerObjectMap = Modbus4jUtils.batchReadAgingCabinetStatus(master, registerOffsets);

                    equipmentInfo.setRegisterValues(integerObjectMap);

                } catch (ModbusInitException e) {
                    // 记录异常数据
                    // 更新老化柜状态（“0”空闲，“1”运行，“2”故障）
                    equipmentInfo.setfStatus("2");
                    equipmentInfo.setErrorReason("定时任务巡检:Modbus初始化失败");
                    equipmentInfo.setRegisterValues(new HashMap<>());
                    // 返回结果
                    return equipmentInfo;
                    // 层有错误返回 柜可能连不上也在这个报错里面
                } catch (ModbusTransportException e) {
                    // 网线没插好通讯不上
                    if (e.getMessage().equals("java.net.SocketTimeoutException: connect timed out")) {
                        // 记录异常数据
                        equipmentInfo.setErrorReason("定时任务巡检:老化柜网线没插好");
                        // 线接错误
                    } else {
                        // 记录异常数据
                        equipmentInfo.setErrorReason("定时任务巡检:老化柜通信线路没接好");
                    }
                    // 更新老化柜状态（“0”空闲，“1”运行，“2”故障）
                    equipmentInfo.setRegisterValues(new HashMap<>());
                    equipmentInfo.setfStatus("2");

                    return equipmentInfo;
                } catch (ErrorResponseException e) {
                    equipmentInfo.setfStatus("2");
                    equipmentInfo.setRegisterValues(new HashMap<>());
                    equipmentInfo.setErrorReason("定时任务巡检:ErrorResponseException");
                    return equipmentInfo;
                } finally {
                    if (master != null) {
                        master.destroy();
                    }
                }
                return equipmentInfo;
            }, executor)).collect(Collectors.toList());

            // 等待所有任务完成并收集结果
            CompletableFuture<List<TEquipmentInfo>> listCompletableFuture = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
                    .thenApply(v -> futures.stream()
                            .map(CompletableFuture::join)
                            .collect(Collectors.toList()));
            // 处理 老化柜 是 运行 开始 空闲
            CompletableFuture<List<TEquipmentInfo>> processedFuture = listCompletableFuture.thenApply(this::processDeviceData);

            processedFuture.whenComplete((result, ex) -> {
                tEquipmentInfoService.batchUpdate(result);
                // 执行WebSocket广播，推送最新老化柜状态
                if (result != null && !result.isEmpty()) {
                    agingCabinetWebSocketHandler.broadcastAgingCabinetData(result);
                    log.info("已通过WebSocket广播{}条老化柜状态数据", result.size());
                }
            });

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //  处理 老化柜 是 运行 开始 空闲
    private List<TEquipmentInfo> processDeviceData(List<TEquipmentInfo> deviceDataList) {

        for (TEquipmentInfo modbusDeviceData : deviceDataList) {
            Map<Integer, Object> registerValues = modbusDeviceData.getRegisterValues();
            // 大于0 说明 柜能通信；小于0 说明柜 不能通信
            if (registerValues.size() > 0) {
                boolean isRun = false;
                for (Map.Entry<Integer, Object> entry : registerValues.entrySet()) {
                    Object registerValue = entry.getValue();
                    if (Boolean.TRUE.equals(registerValue)) {
                        isRun = true;
                    }
                }
                if (isRun) {
                    modbusDeviceData.setfStatus("1");
                } else {
                    modbusDeviceData.setfStatus("0");
                }
            } else {
                modbusDeviceData.setfStatus("2");
            }
        }
        return deviceDataList;
    }
}
