package cn.iocoder.yudao.module.pms.controller.admin.iotopeationfill;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.pms.annotation.AntiDuplicateSubmit;
import cn.iocoder.yudao.module.pms.controller.admin.iotmodeltemplateattrs.vo.IotModelTemplateAttrsRespVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotopeationfill.vo.*;
import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotProjectTaskPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportSaveReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportSaveReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreportdetail.vo.IotRyDailyReportDetailRespVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreportdetail.vo.IotRyDailyReportDetailSaveReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.DeviceTdVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.DeviceVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotcountdata.IotCountDataDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotcountdata.IotCountListDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicecountdata.IotDeviceCountData;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicerunlog.IotDeviceRunLogDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotmodeltemplateattrs.IotModelTemplateAttrsDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotmodeltemplateattrs.IotModelTemplateAttrsDO1;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotopeationfill.IotOpeationFillDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotopeationfill.IotOpeationFillOrderDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttask.IotProjectTaskDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.yanfan.YfDeviceDO;
import cn.iocoder.yudao.module.pms.dal.mysql.iotopeationfill.IotOpeationFillOrderMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotprojecttask.IotProjectTaskMapper;
import cn.iocoder.yudao.module.pms.service.IDeviceService;
import cn.iocoder.yudao.module.pms.service.iotopeationfill.IotOpeationFillService;
import cn.iocoder.yudao.module.pms.service.iotrhdailyreport.IotRhDailyReportService;
import cn.iocoder.yudao.module.pms.service.iotrydailyreport.IotRyDailyReportService;
import cn.iocoder.yudao.module.pms.service.yanfan.YfDeviceService;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dict.DictDataService;
import com.aliyun.tea.utils.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;


@Tag(name = "管理后台 - 运行记录填报")
@RestController
@RequestMapping("/rq/iot-opeation-fill")
@Validated
@Slf4j
public class IotOpeationFillController {

    @Resource
    private IotOpeationFillService iotOpeationFillService;
    @Resource
    private IDeviceService iDeviceService;
    @Autowired
    private YfDeviceService yfDeviceService;
    @Resource
    private DeptService deptService;
    @Resource
    private IotRhDailyReportService iotRhDailyReportService;
    @Resource
    private IotRyDailyReportService iotRyDailyReportService;
    @Resource
    private IotProjectTaskMapper iotProjectTaskMapper;
    @Autowired
    private IotOpeationFillOrderMapper iotOpeationFillOrderMapper;
    @Resource
    private DictDataService dictDataService;

    @PostMapping("/create")
    @Operation(summary = "创建运行记录填报")
    @PreAuthorize("@ss.hasPermission('rq:iot-opeation-fill:create')")
    public CommonResult<Long> createIotOpeationFill(@Valid @RequestBody IotOpeationFillSaveReqVO createReqVO) {
        return success(iotOpeationFillService.createIotOpeationFill(createReqVO));
    }


    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/insertLog")
    @Operation(summary = "创建运行记录填写信息")
    public CommonResult<Integer> insertLog(@Valid @RequestBody OperationFillSaveVO operationFillSaveVO) {
        List<IotOpeationFillSaveReqVO> createReqVO = operationFillSaveVO.getCreateReqVO();
        try{

            List<IotOpeationFillSaveReqVO> fillList = createReqVO;

            for (IotOpeationFillSaveReqVO fill:fillList) {
                //累计并且设置了累计值，数据累加
                //累计并且设置了累计值，数据不累加
                if(fill.getIsSum()==1&&fill.getDefaultValue()!=""&&fill.getSumId()==1){

                    LocalTime localTime = LocalTime.of(0,0);
                    IotDeviceRunLogDO fillLog = new IotDeviceRunLogDO();
                    fillLog.setDeviceId(fill.getDeviceId());
                    fillLog.setPointName(fill.getPointName());
                    fillLog.setCreateTime(LocalDateTime.of(fill.getCreateTime(),localTime));
                    IotDeviceRunLogDO maxFillData = iotOpeationFillService.maxReportData(fillLog);

                    for (IotOpeationFillSaveReqVO fill1:fillList) {
                        if(Long.parseLong(fill.getDefaultValue())==fill1.getModelId()){
                            if(maxFillData!=null){
                                fill.setTotalRunTime(maxFillData.getTotalRunTime().add(new BigDecimal(fill1.getFillContent())));
                            }else{
                                fill.setTotalRunTime(fill.getTotalRunTime().add(new BigDecimal(fill1.getFillContent())));
                            }
                        }
                    }
                }else if(fill.getIsSum()==1&&fill.getDefaultValue()!=""&&fill.getSumId()==0){
                    for (IotOpeationFillSaveReqVO fill1:fillList) {
                        if(Long.parseLong(fill.getDefaultValue())==fill1.getModelId()){
                            fill.setTotalRunTime(new BigDecimal(fill1.getFillContent()));
                        }
                    }
                }
            }

            List< IotDeviceRunLogDO > logDO = new ArrayList<>();

            for (IotOpeationFillSaveReqVO fill:fillList) {

                LocalTime localTime = LocalTime.of(0,0);

                IotDeviceRunLogDO deviceRunLogDO = new IotDeviceRunLogDO();

                deviceRunLogDO.setDeviceId(fill.getDeviceId());
                deviceRunLogDO.setDeviceCode(fill.getDeviceCode());
                deviceRunLogDO.setFillContent(fill.getFillContent());
                deviceRunLogDO.setPointCode(fill.getModelAttr());
                deviceRunLogDO.setDeptId(fill.getDeptId());
                deviceRunLogDO.setCreateTime(LocalDateTime.of(fill.getCreateTime(),localTime));
                deviceRunLogDO.setPointName(fill.getPointName());
                deviceRunLogDO.setTotalRunTime(fill.getTotalRunTime());
                if(fill.getIsSum()==0){
                    deviceRunLogDO.setIsSum(0);
                }else{
                    deviceRunLogDO.setIsSum(1);
                }

                logDO.add(deviceRunLogDO);
            }
            iotOpeationFillService.updateFill(createReqVO.get(0));

            /**
             * 判断设备状态是否都为填写
             * 1、是 更新填写工单为已填写
             * 2、否 更新填写工单为待填写
             * 3、部分填写 更新填写工单为填写中
             */
            IotOpeationFillRespVO respVO = new IotOpeationFillRespVO();
            respVO.setUserId(createReqVO.get(0).getUserId());
            respVO.setCreateTime(createReqVO.get(0).getCreateTime());
            respVO.setOrderId(createReqVO.get(0).getId());
            List<IotOpeationFillRespVO> fillList1 = iotOpeationFillService.getFillList(respVO);

            boolean result = fillList1.stream().allMatch(e->e.getIsFill()==1);
            boolean result1 = fillList1.stream().allMatch(e->e.getIsFill()==0);

            IotDeviceRunLogDO deviceRunLogDO = new IotDeviceRunLogDO();
            deviceRunLogDO.setId(createReqVO.get(0).getId());

            IotOpeationFillDO fillDO = new IotOpeationFillDO();
            fillDO.setOrderId(createReqVO.get(0).getId());

            if(result){
                iotOpeationFillService.updateFillOrder(deviceRunLogDO);

                List<IotOpeationFillDO> devList = iotOpeationFillService.devList(fillDO);
                if(devList.size()==1){
                    fillDO.setDeviceId(devList.get(0).getDeviceId());
                    fillDO.setCreDate(createReqVO.get(0).getCreateTime());
                    List<IotOpeationFillDO> orderList = iotOpeationFillService.orderList(fillDO);
                    if(orderList.size()>0){
                        for (IotOpeationFillDO order:orderList) {
                            List<IotOpeationFillDO> delList = iotOpeationFillService.delList(order);
                            if(delList.size()==1){
                                iotOpeationFillService.delRepeat(delList.get(0));
                                iotOpeationFillService.delRepeatOrder(order);
                            }
                        }
                    }
                }

            }else if(result1){
                iotOpeationFillService.updateFillOrder1(deviceRunLogDO);
            }else{
                iotOpeationFillService.updateFillOrder2(deviceRunLogDO);
            }

            for (IotDeviceRunLogDO log:logDO) {
                //根据设备编码，属性名称和时间查询run_log表
                //有数据则更新，无数据则插入
                IotDeviceRunLogDO fillData = iotOpeationFillService.reportData(log);
                if(fillData == null){
                    iotOpeationFillService.insertLog1(log);
                }else{
                    if(log.getIsSum() == 0){
                        iotOpeationFillService.updateLog(log);
                    }else{
                        iotOpeationFillService.updateSumLog(log);
                    }
                }
            }

            Set<Long> rhIdList = deptService.getChildDeptIdListFromCache(157L);
            rhIdList.add(157L);


            Set<Long> ryIdList =  deptService.getChildDeptIdListFromCache(158L);
            ryIdList.add(158L);


            IotDeviceRunLogDO runDo = logDO.get(0);
            IotOpeationFillDO reportDO = new IotOpeationFillDO();
            reportDO.setDeviceId(runDo.getDeviceId());
            reportDO.setCreateTime(runDo.getCreateTime());
            IotOpeationFillDO fillDO1 = iotOpeationFillService.isReport(reportDO);

            //虚拟设备插入日报
            if(fillDO1.getIsReport()!=null && fillDO1.getIsReport()==1){

                IotRhDailyReportSaveReqVO saveReqVO = new IotRhDailyReportSaveReqVO();
                IotRyDailyReportSaveReqVO saveReqRyVO = new IotRyDailyReportSaveReqVO();

                Map<String,Object> stringRhObjectMap = BeanUtil.beanToMap(saveReqVO);
                Map<String,Object> stringRyObjectMap = BeanUtil.beanToMap(saveReqRyVO);

                if(rhIdList.contains(fillDO1.getDeptId())){
                    for (IotDeviceRunLogDO logDO1:logDO) {

                        IotDeviceRunLogDO descDO = iotOpeationFillService.getDesc(logDO1);

                        if(descDO!=null){
                            stringRhObjectMap.forEach((k,v)->{
                                if(k.equals(descDO.getPointName())){
                                    stringRhObjectMap.put(k,logDO1.getFillContent());
                                }
                            });
                        }
                    }

                    IotRhDailyReportSaveReqVO saveReqVO1 = BeanUtil.mapToBean(stringRhObjectMap,IotRhDailyReportSaveReqVO.class,false);
                    saveReqVO1.setDeptId(fillDO1.getDeptId());
                    saveReqVO1.setFillOrderCreateTime(fillList.get(0).getCreateTime().atStartOfDay());
                    saveReqVO1.setCreator(String.valueOf(fillList.get(0).getUserId()));
                    iotRhDailyReportService.createIotRhDailyReport(saveReqVO1);
                }else if(ryIdList.contains(fillDO1.getDeptId())){
                    for (IotDeviceRunLogDO logDO1:logDO) {

                        IotDeviceRunLogDO descDO = iotOpeationFillService.getDesc(logDO1);

                        if(descDO!=null){
                            stringRyObjectMap.forEach((k,v)->{
                                if(k.equals(descDO.getPointName())){
                                    stringRyObjectMap.put(k,logDO1.getFillContent());
                                }
                            });
                        }
                    }

                    IotRyDailyReportSaveReqVO saveReqVO1 = BeanUtil.mapToBean(stringRyObjectMap, IotRyDailyReportSaveReqVO.class,false);
                    saveReqVO1.setDeptId(fillDO1.getDeptId());
                    saveReqVO1.setFillOrderCreateTime(fillList.get(0).getCreateTime().atStartOfDay());
                    saveReqVO1.setCreator(String.valueOf(fillList.get(0).getUserId()));
                    if(fillDO1.getDeviceCategoryId()==228){
                        saveReqVO1.setProjectClassification("2");
                    }
                    List<IotRyDailyReportDetailSaveReqVO> details = operationFillSaveVO.getReportDetails();
                    saveReqVO1.setReportDetails(details);
                    List<Long> taskIds = new ArrayList<>();
                    if (CollUtil.isNotEmpty(details)) {
                        details.forEach(detail -> {
                            if (ObjUtil.isNotEmpty(detail)) {
                                taskIds.add(detail.getTaskId());
                            }
                        });
                        if (CollUtil.isNotEmpty(taskIds)) {
                            saveReqVO1.setTaskId(taskIds.get(0));
                        }
                    }
                    iotRyDailyReportService.createIotRyDailyReport(saveReqVO1);
                }



            }

            return success(1);


        }catch (Exception e){
            e.printStackTrace();
            return error(1,"插入device_run_log失败");
        }


    }

    //*********APP全部保存接口************
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/insertDataList")
    @Operation(summary = "创建运行记录工单设备集填写信息")
    // 添加防刷注解，5秒内不允许重复请求
    @AntiDuplicateSubmit(timeout = 5, message = "5秒内不允许重复提交，请稍后再试")
    public CommonResult<Integer> insertDataList(@Valid @RequestBody OperationFillAppSaveVO operationFillAppSaveVO) {
        List<IotOperationSaveInfoVO> createReqVO = operationFillAppSaveVO.getCreateReqVO();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String tenantId = request.getHeader("Tenant-Id");

        try {

            TenantContextHolder.setTenantId(Long.parseLong(tenantId)); // 存入上下文（关键步骤）
            // 1. 数据预处理：提取所有设备数据并扁平化
            List<IotOpeationFillSaveReqVO> allFillData = createReqVO.stream()
                    .flatMap(vo -> vo.getDeviceInfoList().stream())
                    .collect(Collectors.toList());


            // 1. 集合类型改为实体类列表
            List<IotOpeationFillSaveReqVO > uniqueDeviceEntities = new ArrayList<>();

            // 空值防护：先判断外层集合是否为null或空
            if (createReqVO != null && !createReqVO.isEmpty()) {
                uniqueDeviceEntities = createReqVO.stream()
                        // 1. 过滤外层集合中：内部 deviceInfoList 为 null 的元素
                        .filter(operationSaveInfo -> operationSaveInfo.getDeviceInfoList() != null)
                        // 2. 展开内层集合（合并为一个流）
                        .flatMap(operationSaveInfo -> operationSaveInfo.getDeviceInfoList().stream())
                        // 3. 过滤内层元素：deviceInfo 为 null 或 deviceId 为 null 的情况
                        .filter(deviceInfo -> deviceInfo != null && deviceInfo.getDeviceId() != null)
                        // 4. 核心修改：提取 deviceId 并创建实体类对象（而非转 String）
                        .map(deviceInfo -> {
                            IotOpeationFillSaveReqVO saveReqVO = new IotOpeationFillSaveReqVO();
                            saveReqVO.setDeviceId(deviceInfo.getDeviceId());
                            saveReqVO.setCreateTime(deviceInfo.getCreateTime());
                            return saveReqVO;
                        })
                        // 5. 去重：需重写实体类的 equals() 和 hashCode()（关键！）
                        .distinct()
                        // 6. 收集为实体类列表
                        .collect(Collectors.toList());
            }


            // 验证数据不为空
            if (CollectionUtils.isEmpty(allFillData)) {
                return error(1, "设备数据不能为空");
            }

            // 2. 批量处理累计逻辑（优化循环，使用Map减少时间复杂度）
            processSummationLogic(allFillData);

            // 3. 批量转换为DO对象
            List<IotDeviceRunLogDO> logDOList = convertToLogDOList(allFillData);

            // 4. 获取工单ID用于后续操作
            Long orderId = allFillData.get(0).getId();
            LocalDate createDate = allFillData.get(0).getCreateTime();
            Integer userId = allFillData.get(0).getUserId();



            // 6. 批量保存日志（有则更新，无则插入）
            batchSaveLogs(logDOList);

            // 7. 获取部门ID集合
            Map<String, Set<Long>> deptMap = getDeptIdSets();

            // 8. 生成日报
            generateDailyReports(logDOList, deptMap, createDate,userId, operationFillAppSaveVO.getReportDetails());

            // 9. 批量更新工单填写状态
            int a = iotOpeationFillService.batchUpdateFill(uniqueDeviceEntities);


                // 5. 更新填写状态
                updateFillOrderStatus(orderId, userId, createDate);


            return success(1);

        } catch (Exception e) {
            //log.error("插入device_run_log失败", e);
            return error(1, "插入device_run_log失败：" + e.getMessage());
        }
    }



    /**
     * 处理累计逻辑（优化后：批量查询历史数据）
     */
    private void processSummationLogic(List<IotOpeationFillSaveReqVO> allFillData) {

        // 前置空校验：避免无效流式处理
        if (allFillData == null || allFillData.isEmpty()) {
            return;
        }

        // 2. 使用Stream.allMatch()判断所有元素是否满足两个条件（同时满足）
        boolean allMatch = allFillData.stream()
                .allMatch(vo -> {
                    // 条件1：isSum == 0（处理包装类型null的情况，避免空指针）
                    boolean isSumEquals0 = Objects.nonNull(vo.getIsSum()) && vo.getIsSum().equals(0);
                    // 条件2：deviceCode 是空串（包含null和""两种情况）
                    // 方式A：使用StringUtils.isEmpty（推荐，简洁）
                    boolean deviceCodeIsEmpty = StringUtils.isEmpty(vo.getDeviceCode());
                    // 方式B：手动双重判断（不依赖第三方工具）
                    // boolean deviceCodeIsEmpty = vo.getDeviceCode() == null || vo.getDeviceCode().trim().isEmpty();

                    // 两个条件必须同时满足（逻辑与 &&）
                    return isSumEquals0 && deviceCodeIsEmpty;
                });
        if(allMatch){
            return;
        }

        // 1. 合并过滤逻辑：一次性过滤出累计数据，按sumId分组（避免两次流式过滤）
        Map<Long, List<IotOpeationFillSaveReqVO>> sumDataGroup = allFillData.stream()
                .filter(fill -> 1 == fill.getIsSum())
                .collect(Collectors.groupingBy(IotOpeationFillSaveReqVO::getSumId));

        // 拆分出两类累计数据（空集合安全处理）
        List<IotOpeationFillSaveReqVO> sumDataList = sumDataGroup.getOrDefault(1L, Collections.emptyList());
        List<IotOpeationFillSaveReqVO> sumDataList1 = sumDataGroup.getOrDefault(0L, Collections.emptyList());


        /*// 1. 提前过滤+非空校验（流式操作简化）RH,RY的累计属性
        List<IotOpeationFillSaveReqVO> sumDataList = allFillData.stream()
                .filter(fill -> 1 == fill.getIsSum())
                .filter(fill -> 1 == fill.getSumId())
                .collect(Collectors.toList());
        //瑞都累计属性
        List<IotOpeationFillSaveReqVO> sumDataList1 = allFillData.stream()
                .filter(fill -> 1 == fill.getIsSum())
                .filter(fill -> 0 == fill.getSumId())
                .collect(Collectors.toList());*/


        // 2. 构建unSumData的索引（设备ID + 模型ID），避免嵌套循环
        // 键：deviceId_modelId，值：该维度下的fillContent数值
        Map<String, BigDecimal> unSumDataIndex = allFillData.stream()
                .filter(fill -> 0 == fill.getIsSum() && fill.getDeviceCode() != null
                        && !fill.getDeviceCode().isEmpty())
                .filter(fill -> {
                    String content = String.valueOf(fill.getFillContent()).trim();
                    // 排除空字符串和非数字（支持整数、小数，不支持文本）
                    return !content.isEmpty() && content.matches("^[+-]?\\d+(\\.\\d+)?$");
                })
                .collect(Collectors.toMap(
                        fill -> fill.getDeviceId() + "_" + fill.getModelId(), // 构建索引键
                        fill -> new BigDecimal(String.valueOf(fill.getFillContent()).trim()), // 提前转换为BigDecimal
                        (v1, v2) -> v1.add(v2) // 同维度数据直接累加（根据业务调整，此处默认累加）
                ));

        // 3. 批量构建查询条件（简化流式操作）
        List<IotDeviceRunLogDO> queryLogs = new ArrayList<>();
        if(!sumDataList.isEmpty()){
            queryLogs = sumDataList.stream()
                    .map(fill -> {
                        IotDeviceRunLogDO queryLog = new IotDeviceRunLogDO();
                        queryLog.setDeviceId(fill.getDeviceId());
                        queryLog.setPointName(fill.getPointName());
                        queryLog.setCreateTime(LocalDateTime.of(fill.getCreateTime(), LocalTime.MIDNIGHT));
                        return queryLog;
                    })
                    .collect(Collectors.toList());
        }
        if(!sumDataList1.isEmpty()){
            queryLogs = sumDataList1.stream()
                    .map(fill -> {
                        IotDeviceRunLogDO queryLog = new IotDeviceRunLogDO();
                        queryLog.setDeviceId(fill.getDeviceId());
                        queryLog.setPointName(fill.getPointName());
                        queryLog.setCreateTime(LocalDateTime.of(fill.getCreateTime(), LocalTime.MIDNIGHT));
                        return queryLog;
                    })
                    .collect(Collectors.toList());
        }


        // 4. 批量查询历史最大数据（原逻辑保留，1次数据库交互）
        List<IotDeviceRunLogDO> maxFillDataList = iotOpeationFillService.batchQueryMaxReportData(queryLogs);
        Map<String, BigDecimal> maxDataMap = maxFillDataList.stream()
                .filter(data -> data.getTotalRunTime() != null)
                .collect(Collectors.toMap(
                        data -> data.getDeviceId() + "_" + data.getPointName(),
                        IotDeviceRunLogDO::getTotalRunTime,
                        (v1, v2) -> v1 // 保留第一个值（业务确认）
                ));

        // 5. 并行处理累计计算（CPU密集型，使用parallelStream+提前解析参数）
        sumDataList.forEach(fill -> {
            try {
                // 提前解析defaultValue（模型ID），避免循环内重复解析
                Long modelId = Long.parseLong(fill.getDefaultValue());
                // 构建索引键：deviceId_modelId
                String unSumKey = fill.getDeviceId() + "_" + modelId;
                // 从索引获取目标数值（O(1)查询）
                BigDecimal currentValue = unSumDataIndex.getOrDefault(unSumKey, BigDecimal.ZERO);

                // 构建历史数据键（提前拼接，避免重复）
                String historyKey = fill.getDeviceId() + "_" + fill.getPointName();
                BigDecimal maxHistory = maxDataMap.getOrDefault(historyKey, BigDecimal.ZERO);

                //RH,RY累计等于历史最大值+当日填写值
                BigDecimal total = maxHistory.add(currentValue);
                fill.setTotalRunTime(total);

            } catch (NumberFormatException e) {
                // 补充日志，便于问题排查
                log.warn("累计数据处理失败：defaultValue转换异常，fillId={}, defaultValue={}",
                        fill.getId(), fill.getDefaultValue(), e);
            } catch (Exception e) {
                // 兜底异常处理，避免单条数据失败导致整体中断
                log.error("累计数据处理异常：fillId={}", fill.getId(), e);
            }
        });
        sumDataList1.forEach(fill->{
            try {
                // 提前解析defaultValue（模型ID），避免循环内重复解析
                Long modelId = Long.parseLong(fill.getDefaultValue());
                // 构建索引键：deviceId_modelId
                String unSumKey = fill.getDeviceId() + "_" + modelId;
                // 从索引获取目标数值（O(1)查询）
                BigDecimal currentValue = unSumDataIndex.getOrDefault(unSumKey, BigDecimal.ZERO);
                fill.setTotalRunTime(currentValue);

            } catch (NumberFormatException e) {
                // 补充日志，便于问题排查
                log.warn("累计数据处理失败：defaultValue转换异常，fillId={}, defaultValue={}",
                        fill.getId(), fill.getDefaultValue(), e);
            } catch (Exception e) {
                // 兜底异常处理，避免单条数据失败导致整体中断
                log.error("累计数据处理异常：fillId={}", fill.getId(), e);
            }
        });
    }







    /**
     * 批量转换为DO对象
     */
    private List<IotDeviceRunLogDO> convertToLogDOList(List<IotOpeationFillSaveReqVO> allFillData) {
        LocalTime localTime = LocalTime.MIDNIGHT;

        return allFillData.stream()
                .map(fill -> {
                    IotDeviceRunLogDO deviceRunLogDO = new IotDeviceRunLogDO();
                    deviceRunLogDO.setDeviceId(fill.getDeviceId());
                    deviceRunLogDO.setDeviceCode(fill.getDeviceCode());
                    deviceRunLogDO.setFillContent(fill.getFillContent());
                    deviceRunLogDO.setPointCode(fill.getModelAttr());
                    deviceRunLogDO.setDeptId(fill.getDeptId());
                    deviceRunLogDO.setCreateTime(LocalDateTime.of(fill.getCreateTime(), localTime));
                    deviceRunLogDO.setPointName(fill.getPointName());
                    deviceRunLogDO.setTotalRunTime(fill.getTotalRunTime());
                    deviceRunLogDO.setIsSum(fill.getIsSum() != null ? fill.getIsSum() : 0);
                    return deviceRunLogDO;
                })
                .collect(Collectors.toList());
    }

    /**
     * 更新填写工单状态
     */
    private void updateFillOrderStatus(Long orderId, Integer userId, LocalDate createDate) {
        IotOpeationFillRespVO queryVO = new IotOpeationFillRespVO();
        queryVO.setUserId(userId);
        queryVO.setCreateTime(createDate);
        queryVO.setOrderId(orderId);

        List<IotOpeationFillRespVO> fillList = iotOpeationFillService.getFillList(queryVO);

        if (CollectionUtils.isEmpty(fillList)) {
            return;
        }

        boolean allFilled = fillList.stream().allMatch(e -> e.getIsFill() == 1);
        boolean allUnfilled = fillList.stream().allMatch(e -> e.getIsFill() == 0);

        IotDeviceRunLogDO updateParam = new IotDeviceRunLogDO();
        updateParam.setId(orderId);

        if (allFilled) {
            iotOpeationFillService.updateFillOrder(updateParam);
            handleDuplicateOrders(orderId, createDate);
        } else if (allUnfilled) {
            iotOpeationFillService.updateFillOrder1(updateParam);
        } else {
            iotOpeationFillService.updateFillOrder2(updateParam);
        }
    }

    /**
     * 处理重复订单
     */
    private void handleDuplicateOrders(Long orderId, LocalDate createDate) {
        IotOpeationFillDO queryDO = new IotOpeationFillDO();
        queryDO.setOrderId(orderId);

        List<IotOpeationFillDO> devList = iotOpeationFillService.devList(queryDO);

        if (devList.size() == 1) {
            queryDO.setDeviceId(devList.get(0).getDeviceId());
            queryDO.setCreDate(createDate);

            List<IotOpeationFillDO> orderList = iotOpeationFillService.orderList(queryDO);

            if (!CollectionUtils.isEmpty(orderList)) {
                for (IotOpeationFillDO order : orderList) {
                    List<IotOpeationFillDO> delList = iotOpeationFillService.delList(order);
                    if (delList.size() == 1) {
                        iotOpeationFillService.delRepeat(delList.get(0));
                        iotOpeationFillService.delRepeatOrder(order);
                    }
                }
            }
        }
    }


    /**
     * 批量保存日志（优化后：批量查询+批量插入+批量更新）
     */
    private void batchSaveLogs(List<IotDeviceRunLogDO> logDOList) {
        if (CollectionUtils.isEmpty(logDOList)) {
            return;
        }

        // 1. 批量查询已存在的数据（用复合索引：deviceId+pointName+createTime）
        List<IotDeviceRunLogDO> existingLogs = iotOpeationFillService.batchQueryExistingLogs(logDOList);
        Map<String, IotDeviceRunLogDO> existingLogMap = existingLogs.stream()
                .collect(Collectors.toMap(
                        log -> buildLogUniqueKey(log), // 构建唯一标识：deviceId_pointName_createTime
                        log -> log,
                        (v1, v2) -> v1 // 避免重复key（理论上不会有）
                ));


        // 2. 拆分：待插入列表 + 待更新列表
        List<IotDeviceRunLogDO> insertList = new ArrayList<>();
        List<IotDeviceRunLogDO> updateList = new ArrayList<>();
        List<IotDeviceRunLogDO> updateSumList = new ArrayList<>();

        for (IotDeviceRunLogDO log : logDOList) {
            String key = buildLogUniqueKey(log);
            if (existingLogMap.containsKey(key)) {
                // 已存在：区分普通更新和累计更新
                if (log.getIsSum() == 0) {
                    updateList.add(log);
                } else {
                    updateSumList.add(log);
                }
            } else {
                // 不存在：插入
                insertList.add(log);
            }
        }

        // 3. 批量执行（MyBatis批量操作）
        if (!insertList.isEmpty()) {

            TenantUtils.execute(1L, () -> {
                iotOpeationFillService.batchInsertLogs(insertList); // 批量插入
            });
        }
        if (!updateList.isEmpty()) {

            TenantUtils.execute(1L, () -> {
                iotOpeationFillService.batchUpdateLogs(updateList); // 批量更新普通日志
            });
        }
        if (!updateSumList.isEmpty()) {

            TenantUtils.execute(1L, () -> {
                iotOpeationFillService.batchUpdateSumLogs(updateSumList); // 批量更新累计日志
            });
        }
    }

    /**
     * 构建日志唯一标识（用于快速查找已存在数据）
     */
    private String buildLogUniqueKey(IotDeviceRunLogDO log) {
        return log.getDeviceId() + "_" + log.getPointName() + "_" + log.getCreateTime().toLocalDate();
    }

    //*******************批量保存到这********************

    /**
     * 获取部门ID集合
     */
    private Map<String, Set<Long>> getDeptIdSets() {
        Map<String, Set<Long>> deptMap = new HashMap<>();

        Set<Long> rhIdList = deptService.getChildDeptIdListFromCache(157L);
        rhIdList.add(157L);
        deptMap.put("RH", rhIdList);

        Set<Long> ryIdList = deptService.getChildDeptIdListFromCache(158L);
        ryIdList.add(158L);
        deptMap.put("RY", ryIdList);

        return deptMap;
    }


    private void generateDailyReports(List<IotDeviceRunLogDO> logDOList,
                                      Map<String, Set<Long>> deptMap,
                                      LocalDate createDate,
                                      Integer userId, List<IotRyDailyReportDetailSaveReqVO> reportDetails) {
        if (CollectionUtils.isEmpty(logDOList)) {
            return;
        }

        // 1. 批量查询所有测点描述（1次数据库交互，避免循环查询）
        Set<String> pointNameSet = logDOList.stream()
                .map(IotDeviceRunLogDO::getPointName)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        List<IotDeviceRunLogDO> descList = iotOpeationFillService.batchGetDescByPointNames(pointNameSet);
        Map<String, IotDeviceRunLogDO> descMap = descList.stream()
                .collect(Collectors.toMap(
                        IotDeviceRunLogDO::getPointName,
                        desc -> desc,
                        (v1, v2) -> v1
                ));

        // 2. 按设备分组（不变）
        Map<Long, List<IotDeviceRunLogDO>> deviceLogsMap = logDOList.stream()
                .collect(Collectors.groupingBy(IotDeviceRunLogDO::getDeviceId));

        // 3. 并行处理每个设备的日报（IO密集型，并行提速）
        deviceLogsMap.entrySet().parallelStream().forEach(entry -> {
            List<IotDeviceRunLogDO> deviceLogs = entry.getValue();
            IotDeviceRunLogDO sampleLog = deviceLogs.get(0);

            // 查询上报状态（单条查询无法避免，但并行执行）
            IotOpeationFillDO reportQuery = new IotOpeationFillDO();
            reportQuery.setDeviceId(sampleLog.getDeviceId());
            reportQuery.setCreateTime(sampleLog.getCreateTime());
            IotOpeationFillDO fillStatus = iotOpeationFillService.isReport(reportQuery);

            if (fillStatus != null && fillStatus.getIsReport() != null && fillStatus.getIsReport() == 1) {
                fillStatus.setUserId(userId);
                // 处理部门日报
                processDepartmentReport(deviceLogs, fillStatus, deptMap, createDate, descMap, reportDetails);
            }
        });
    }



    /**
     * 处理部门日报生成（新增descMap缓存）
     */
    private void processDepartmentReport(List<IotDeviceRunLogDO> deviceLogs,
                                         IotOpeationFillDO fillStatus,
                                         Map<String, Set<Long>> deptMap,
                                         LocalDate createDate,
                                         Map<String, IotDeviceRunLogDO> descMap, List<IotRyDailyReportDetailSaveReqVO> reportDetails) {
        Set<Long> rhIdList = deptMap.get("RH");
        Set<Long> ryIdList = deptMap.get("RY");

        if (rhIdList.contains(fillStatus.getDeptId())) {
            generateRhDailyReport(deviceLogs, fillStatus, createDate, descMap);
        } else if (ryIdList.contains(fillStatus.getDeptId())) {
            generateRyDailyReport(deviceLogs, fillStatus, createDate, descMap, reportDetails);
        }
    }



    /**
     * 生成RH日报（使用缓存的descMap）
     */
    private void generateRhDailyReport(List<IotDeviceRunLogDO> deviceLogs,
                                       IotOpeationFillDO fillStatus,
                                       LocalDate createDate,
                                       Map<String, IotDeviceRunLogDO> descMap) {
        IotRhDailyReportSaveReqVO saveReqVO = new IotRhDailyReportSaveReqVO();
        Map<String, Object> reportData = BeanUtil.beanToMap(saveReqVO);

        for (IotDeviceRunLogDO log : deviceLogs) {
            IotDeviceRunLogDO descDO = iotOpeationFillService.getDesc(log);
            if (descDO != null && reportData.containsKey(descDO.getPointName())) {
                reportData.put(descDO.getPointName(), log.getFillContent());
            }
        }

        // 后续赋值和保存逻辑不变（建议日报也做批量保存，若存在多条设备）
        IotRhDailyReportSaveReqVO finalReport = BeanUtil.mapToBean(reportData, IotRhDailyReportSaveReqVO.class, false);
        finalReport.setDeptId(fillStatus.getDeptId());
        finalReport.setFillOrderCreateTime(createDate.atStartOfDay());
        finalReport.setCreator(String.valueOf(fillStatus.getUserId()));
        TenantUtils.execute(1L, () -> {
            iotRhDailyReportService.createIotRhDailyReport(finalReport);
        });
    }


    private void generateRyDailyReport(List<IotDeviceRunLogDO> deviceLogs,
                                       IotOpeationFillDO fillStatus,
                                       LocalDate createDate,
                                       Map<String, IotDeviceRunLogDO> descMap, List<IotRyDailyReportDetailSaveReqVO> reportDetails) {
        IotRyDailyReportSaveReqVO saveReqVO = new IotRyDailyReportSaveReqVO();
        Map<String, Object> reportData = BeanUtil.beanToMap(saveReqVO);

        IotOpeationFillDO reportDO = new IotOpeationFillDO();
        for (IotDeviceRunLogDO log : deviceLogs) {
            //IotDeviceRunLogDO descDO = descMap.get(log.getPointName()); // 从缓存获取，无数据库交互
            IotDeviceRunLogDO descDO = iotOpeationFillService.getDesc(log);
            if (descDO != null && reportData.containsKey(descDO.getPointName())) {
                reportData.put(descDO.getPointName(), log.getFillContent());
            }

            reportDO.setDeviceId(log.getDeviceId());
            reportDO.setCreateTime(log.getCreateTime());
            IotOpeationFillDO fillDO1 = iotOpeationFillService.isReport(reportDO);
            if(fillDO1.getDeviceCategoryId()==228){
                reportData.put("projectClassification","2");
            }
        }

        // 后续赋值和保存逻辑不变（建议日报也做批量保存，若存在多条设备）
        IotRyDailyReportSaveReqVO finalReport = BeanUtil.mapToBean(reportData, IotRyDailyReportSaveReqVO.class, false);
        finalReport.setDeptId(fillStatus.getDeptId());
        finalReport.setFillOrderCreateTime(createDate.atStartOfDay());
        finalReport.setCreator(String.valueOf(fillStatus.getUserId()));
        finalReport.setReportDetails(reportDetails);
        TenantUtils.execute(1L, () -> {
            iotRyDailyReportService.createIotRyDailyReport(finalReport);
        });
    }

    //************************************************8

    @PostMapping("/upOperationOrder")
    @Operation(summary = "创建运行记录填写信息")
    public CommonResult<Integer> upOperationOrder(@Valid @RequestBody IotOpeationFillRespVO respVO) {

        List<IotOpeationFillRespVO> fillList1 = iotOpeationFillService.getFillList(respVO);

        boolean result = fillList1.stream().allMatch(e->e.getIsFill()==1);

        IotDeviceRunLogDO deviceRunLogDO = new IotDeviceRunLogDO();
        deviceRunLogDO.setId(respVO.getId());

        if(result){
            iotOpeationFillService.updateFillOrder(deviceRunLogDO);
        }

        return success(1);
    }



    @PutMapping("/update")
    @Operation(summary = "更新运行记录填报")
    @PreAuthorize("@ss.hasPermission('rq:iot-opeation-fill:update')")
    public CommonResult<Boolean> updateIotOpeationFill(@Valid @RequestBody IotOpeationFillSaveReqVO updateReqVO) {
        iotOpeationFillService.updateIotOpeationFill(updateReqVO);
        return success(true);
    }


    @PutMapping("/update1")
    @Operation(summary = "更新运行记录填报")
    @PreAuthorize("@ss.hasPermission('rq:iot-opeation-fill:update')")
    public CommonResult<Boolean> updateIotOpeationFill1(@Valid @RequestBody IotOpeationFillSaveReqVO updateReqVO) {
        iotOpeationFillService.upFill1(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除运行记录填报")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('rq:iot-opeation-fill:delete')")
    public CommonResult<Boolean> deleteIotOpeationFill(@RequestParam("id") Long id) {
        iotOpeationFillService.deleteIotOpeationFill(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得运行记录填报")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('rq:iot-opeation-fill:query')")
    public CommonResult<IotOpeationFillDO> getIotOpeationFill(@RequestParam("id") Long id) {
        IotOpeationFillDO fillDO = new IotOpeationFillDO();
        fillDO.setId(id);
        IotOpeationFillDO iotOpeationFill = iotOpeationFillService.getFillById(fillDO);
        Map<Long, String> wellNamePair = new HashMap<>();
        iotOpeationFill.setWellNamePair(wellNamePair);
        TenantUtils.executeIgnore(() -> {
            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
            reqVO.setDeptId(iotOpeationFill.getDeptId());
            reqVO.setJobFlag("Y");
            // 查询 瑞恒 施工工艺数据字典
            Set<String> rhTechValues = new HashSet<>();
            List<DictDataDO> rhTechs = dictDataService.getDictDataListByDictType("rq_iot_project_technology_rh");
            if (CollUtil.isNotEmpty(rhTechs)) {
                rhTechs.forEach(tech -> {
                    if ("NOGAS".equals(tech.getRemark())) {
                        rhTechValues.add(tech.getValue());
                    }
                });
            }
            List<IotProjectTaskDO> tasks = iotProjectTaskMapper.selectList(reqVO);
                    if (CollUtil.isNotEmpty(tasks)) {
                        // key任务井id  value注气量是否必填
                        Set<Long> noGasTasks = new HashSet<>();
                        // 取最新的1个任务
                        iotOpeationFill.setWellName(tasks.get(0).getWellName());
                        tasks.forEach(task -> {
                            wellNamePair.put(task.getId(), task.getWellName());
                            // 施工工艺为 调驱 或 泡沫 注气量 非必填
                            if (rhTechValues.contains(task.getTechnique())) {
                                // 施工工艺为 调驱 或 泡沫 注气量 非必填
                                noGasTasks.add(task.getId());
                            }
                        });
                        iotOpeationFill.setWellNamePair(wellNamePair);
                        iotOpeationFill.setNoGasTasks(noGasTasks);
                    }
                    // 查询当前队伍是否已经生成日报 回显数据
                    // 查询日报表中对应日期 对应部门的taskId
                    String reportDateStr = StrUtil.EMPTY;
                    if (ObjUtil.isNotEmpty(iotOpeationFill.getCreateTime())) {
                        reportDateStr = LocalDateTimeUtil.format(iotOpeationFill.getCreateTime(), DatePattern.NORM_DATE_PATTERN);
                    }
                    Long deptId = iotOpeationFill.getDeptId();
                    // 判断当前队伍是 瑞恒 还是 瑞鹰
                    Set<Long> rhChildDeptIds = deptService.getChildDeptIdListFromCache(157l);
                    Set<Long> ryChildDeptIds = deptService.getChildDeptIdListFromCache(158l);
                    if (ObjUtil.isNotEmpty(deptId) && StrUtil.isNotBlank(reportDateStr)) {
                        if (rhChildDeptIds.contains(deptId)) {
                            // 瑞恒日报
                            IotOpeationFillDO taskWellPair = iotOpeationFillService.selectRhFillReports(deptId, reportDateStr);
                            if (ObjUtil.isNotEmpty(taskWellPair)) {
                                wellNamePair.clear();
                                wellNamePair.put(taskWellPair.getTaskId(), taskWellPair.getWellName());
                                iotOpeationFill.setWellNamePair(wellNamePair);
                            }
                        }
                        if (ryChildDeptIds.contains(deptId)) {
                            // 瑞鹰日报
                            IotOpeationFillDO taskWellPair = iotOpeationFillService.selectRyFillReports(deptId, reportDateStr);
                            if (ObjUtil.isNotEmpty(taskWellPair)) {
                                wellNamePair.clear();
                                wellNamePair.put(taskWellPair.getTaskId(), taskWellPair.getWellName());
                                iotOpeationFill.setWellNamePair(wellNamePair);
                            }
                        }
                    }
        });
        return success(BeanUtils.toBean(iotOpeationFill, IotOpeationFillDO.class));
    }



    @GetMapping("/page1")
    @Operation(summary = "获得运行记录填报分页")
    @PreAuthorize("@ss.hasPermission('rq:iot-opeation-fill:query')")
    public CommonResult<PageResult<IotOpeationFillOrderDO>> getIotOpeationFillPage1(@Valid IotOpeationFillPageReqVO pageReqVO) {

        Set<Long> idList = new HashSet<>();
        if(Objects.nonNull(pageReqVO.getDeptId())){
            idList =  deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
            idList.add(pageReqVO.getDeptId());
        }

        PageResult<IotOpeationFillOrderDO> fillList = iotOpeationFillService.fillList2(pageReqVO,idList);
        // 处理时间字段
        if (fillList != null && CollectionUtils.isNotEmpty(fillList.getList())) {
            for (IotOpeationFillOrderDO record : fillList.getList()) {
                LocalDateTime createTime = record.getCreateTime();
                LocalDateTime updateTime = record.getUpdateTime();

                if (createTime != null && updateTime != null && createTime.isEqual(updateTime)) {
                    record.setUpdateTime(null); // 相等时将updateTime置为null
                }
            }
        }

        /* IotOpeationFillRespVO fill = new IotOpeationFillRespVO();

         *//**
         * 遍历主表数据，拿到id,根据id查询子表获取子表设备名称+设备编码
         *//*
        for (IotOpeationFillOrderDO orderDO : fillList.getList()) {
            fill.setOrderId(orderDO.getId());
            fill.setDeptId(orderDO.getDeptId());
            List<IotOpeationFillDO> dList = iotOpeationFillService.fillListByDeptId(fill);
            IotOpeationFillDO devList = iotOpeationFillService.devListByOrderId(fill);
            if(dList.size()>0){
                List<String> detail = new ArrayList<>();
                for (IotOpeationFillDO fillDO:dList) {
                    String a = fillDO.getDeviceCode()+"/"+fillDO.getDeviceName();
                    detail.add(a);
                }
                orderDO.setFillList(detail.toString().substring(1, detail.toString().length() - 1));
                orderDO.setAllDev(devList.getAllDev());
                orderDO.setFillDev(devList.getFillDev());
                orderDO.setUnFillDev(devList.getUnFillDev());
            }
        }*/


        // 收集所有订单ID和部门ID的映射关系
        Map<Long, Long> orderDeptMap = fillList.getList().stream()
                .collect(Collectors.toMap(IotOpeationFillOrderDO::getId, IotOpeationFillOrderDO::getDeptId));

        // 准备查询参数


        // 2. 批量查询所有fill数据
        List<IotOpeationFillDO> allFillList = new ArrayList<>();
        for (Map.Entry<Long, Long> entry : orderDeptMap.entrySet()) {
            IotOpeationFillRespVO fill = new IotOpeationFillRespVO();
            fill.setOrderId(entry.getKey());
            fill.setDeptId(entry.getValue());
            allFillList.addAll(iotOpeationFillService.fillListByDeptId(fill));
        }

        // 3. 批量查询所有dev数据
        Map<Long, IotOpeationFillDO> devMap = new HashMap<>();
        for (Map.Entry<Long, Long> entry : orderDeptMap.entrySet()) {
            IotOpeationFillRespVO fill1 = new IotOpeationFillRespVO();
            fill1.setOrderId(entry.getKey());
            fill1.setDeptId(entry.getValue());
            devMap.put(entry.getKey(), iotOpeationFillService.devListByOrderId(fill1));
        }

        // 4. 将fill数据按订单ID分组
        Map<Long, List<IotOpeationFillDO>> fillMap = allFillList.stream()
                .collect(Collectors.groupingBy(IotOpeationFillDO::getOrderId)); // 假设IotOpeationFillDO有getOrderId方法

        // 查询所有工单部门对应的队伍


        // 5. 遍历处理结果
        for (IotOpeationFillOrderDO orderDO : fillList.getList()) {
            Long orderId = orderDO.getId();
            List<IotOpeationFillDO> dList = fillMap.getOrDefault(orderId, Collections.emptyList());

            if (!dList.isEmpty()) {
                StringJoiner joiner = new StringJoiner(", ");
                for (IotOpeationFillDO fillDO : dList) {
                    joiner.add(fillDO.getDeviceCode() + "/" + fillDO.getDeviceName());
                }
                orderDO.setFillList(joiner.toString());

                IotOpeationFillDO devList = devMap.get(orderId);
                if (devList != null) {
                    orderDO.setAllDev(devList.getAllDev());
                    orderDO.setFillDev(devList.getFillDev());
                    orderDO.setUnFillDev(devList.getUnFillDev());
                }
            }
        }



        return success(BeanUtils.toBean(fillList, IotOpeationFillOrderDO.class));
    }


    @GetMapping("/page")
    @Operation(summary = "获得运行记录填报分页")
    @PreAuthorize("@ss.hasPermission('rq:iot-opeation-fill:query')")
    public CommonResult<List<IotOpeationFillDO>> getIotOpeationFillPage(@Valid IotOpeationFillRespVO pageReqVO) {
        List<IotOpeationFillDO> fillList = iotOpeationFillService.fillListByUserId(pageReqVO);
        // 查询 生产日报 当前队伍对应的 任务井 deviceName = '生产日报'

        if (CollUtil.isNotEmpty(fillList)) {
            TenantUtils.executeIgnore(() -> {
                fillList.forEach(fill -> {
                    if ("生产日报".equals(fill.getDeviceName())) {
                        // 查询施工工艺数据字典
                        Set<String> rhTechValues = new HashSet<>();
                        List<DictDataDO> rhTechs = dictDataService.getDictDataListByDictType("rq_iot_project_technology_rh");
                        if (CollUtil.isNotEmpty(rhTechs)) {
                            rhTechs.forEach(tech -> {
                                if ("NOGAS".equals(tech.getRemark())) {
                                    rhTechValues.add(tech.getValue());
                                }
                            });
                        }
                        fill.getDeptId();
                        IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
                        reqVO.setDeptId(fill.getDeptId());
                        reqVO.setJobFlag("Y");
                        List<IotProjectTaskDO> tasks = iotProjectTaskMapper.selectList(reqVO);
                        // 查询日报表中对应日期 对应部门的taskId
                        String reportDateStr = StrUtil.EMPTY;
                        if (ObjUtil.isNotEmpty(fill.getCreateTime())) {
                            reportDateStr = LocalDateTimeUtil.format(fill.getCreateTime(), DatePattern.NORM_DATE_PATTERN);
                        }
                        Long deptId = fill.getDeptId();
                        // 判断当前队伍是 瑞恒 还是 瑞鹰
                        Set<Long> rhChildDeptIds = deptService.getChildDeptIdListFromCache(157l);
                        Set<Long> ryChildDeptIds = deptService.getChildDeptIdListFromCache(158l);
                        // key任务井id  value任务井号
                        Map<Long, String> wellNamePair = new HashMap<>();
                        // key任务井id  value注气量是否必填
                        Set<Long> noGasTasks = new HashSet<>();
                        if (CollUtil.isNotEmpty(tasks)) {
                            // 取最新的1个任务
                            fill.setWellName(tasks.get(0).getWellName());
                            tasks.forEach(task -> {
                                wellNamePair.put(task.getId(), task.getWellName());
                                if (rhTechValues.contains(task.getTechnique())) {
                                    // 施工工艺为 调驱 或 泡沫 注气量 非必填
                                    noGasTasks.add(task.getId());
                                }
                            });
                            fill.setWellNamePair(wellNamePair);
                            fill.setNoGasTasks(noGasTasks);
                        }
                        if (ObjUtil.isNotEmpty(deptId) && StrUtil.isNotBlank(reportDateStr)) {
                            if (rhChildDeptIds.contains(deptId)) {
                                // 瑞恒日报
                                IotOpeationFillDO taskWellPair = iotOpeationFillService.selectRhFillReports(deptId, reportDateStr);
                                if (ObjUtil.isNotEmpty(taskWellPair)) {
                                    wellNamePair.clear();
                                    wellNamePair.put(taskWellPair.getTaskId(), taskWellPair.getWellName());
                                    fill.setWellNamePair(wellNamePair);
                                }
                            }
                            if (ryChildDeptIds.contains(deptId)) {
                                // 瑞鹰日报
                                IotOpeationFillDO taskWellPair = iotOpeationFillService.selectRyFillReports(deptId, reportDateStr);
                                if (ObjUtil.isNotEmpty(taskWellPair)) {
                                    wellNamePair.clear();
                                    wellNamePair.put(taskWellPair.getTaskId(), taskWellPair.getWellName());
                                    fill.setWellNamePair(wellNamePair);
                                }
                            }
                        }
                    }
                });
            });
        }
        return success(BeanUtils.toBean(fillList, IotOpeationFillDO.class));
    }

    @GetMapping("/orderFillpage")
    @Operation(summary = "获得运行记录填报分页")
    @PreAuthorize("@ss.hasPermission('rq:iot-opeation-fill:query')")
    public CommonResult<PageResult<IotOpeationFillDO>> getIotOpeationFillWithAttrsPage(@Valid IotOpeationFillPageVO pageReqVO) {
        PageResult<IotOpeationFillDO> fillList = iotOpeationFillService.fillListPage(pageReqVO);
        return success(BeanUtils.toBean(fillList, IotOpeationFillDO.class));
    }


    //**************

    @GetMapping("/orderFillpage1")
    @Operation(summary = "获得运行记录填报分页")
    @PreAuthorize("@ss.hasPermission('rq:iot-opeation-fill:query')")
    public CommonResult<PageResult<IotOpeationFillWithAttrsVO>> getIotOpeationFillWithAttrsPage1(
            @Valid IotOpeationFillPageVO pageReqVO) throws Exception {

        // 1. 分页查询主数据（不变）
        PageResult<IotOpeationFillDO> fillPage = iotOpeationFillService.fillListPage(pageReqVO);
        List<IotOpeationFillDO> fillList = fillPage.getList();
        /*if (CollectionUtils.isEmpty(fillList)) {
            return success(BeanUtils.toBean(fillList, IotOpeationFillWithAttrsVO.class));

        }*/

        // 2. 批量预处理参数，避免循环中重复操作
        //List<Long> deviceIds = fillList.stream().map(IotOpeationFillDO::getDeviceId).distinct().collect(Collectors.toList());
        List<String> deviceCodes = fillList.stream().map(IotOpeationFillDO::getDeviceCode).distinct().collect(Collectors.toList());
        //Set<LocalDate> createDates = fillList.stream().map(doObj -> doObj.getCreateTime().toLocalDate()).collect(Collectors.toSet());

        // 3. 批量查询公共数据（一次查询，全局复用）
        // 3.1 批量查询设备状态（判断是否为虚拟设备）
        List<YfDeviceDO> allDevice = yfDeviceService.getAllDevice(); // 仅查1次，而非循环中查N次
        Map<String, YfDeviceDO> deviceStatusMap = allDevice.stream()
                .collect(Collectors.toMap(
                        YfDeviceDO::getSerialNumber,
                        Function.identity(),
                        (oldVal, newVal) -> newVal
                ));
        // 3.2 批量查询isReport状态（避免循环查询）
        Map<Long, Integer> deviceReportMap = iotOpeationFillService.batchGetIsReport(
                fillList.stream().map(doObj -> {
                    IotOpeationFillDO query = new IotOpeationFillDO();
                    query.setDeviceId(doObj.getDeviceId());
                    query.setCreateTime(doObj.getCreateTime().toLocalDate().atStartOfDay());
                    return query;
                }).collect(Collectors.toList())
        );
        // 3.3 批量查询orderDO数据
        Map<Long, IotOpeationFillDO> deviceOrderMap = iotOpeationFillService.batchGetOrderDO(
                fillList.stream().map(doObj -> {
                    IotOpeationFillDO query = new IotOpeationFillDO();
                    query.setDeviceId(doObj.getDeviceId());
                    query.setCreateTime(doObj.getCreateTime().toLocalDate().atStartOfDay());
                    return query;
                }).collect(Collectors.toList())
        );

        // 4. 并行处理分页数据（利用多核CPU，非IO密集型操作适合并行）
        List<IotOpeationFillWithAttrsVO> resultList = fillList.parallelStream().map(fillDO -> {
            try {
                IotOpeationFillWithAttrsVO vo = BeanUtils.toBean(fillDO, IotOpeationFillWithAttrsVO.class);
                LocalDate createDate = fillDO.getCreateTime().toLocalDate();

                // 构建参数VO
                IotModelTemplateAttrsRespVO attrsReqVO = new IotModelTemplateAttrsRespVO();
                attrsReqVO.setDeviceId(fillDO.getDeviceId());
                attrsReqVO.setDeviceCode(fillDO.getDeviceCode());
                attrsReqVO.setCreateTime(createDate);
                attrsReqVO.setDeviceCategoryId(fillDO.getDeviceCategoryId());
                // 调用优化后的属性详情查询（带缓存和批量查询）
                List<IotModelTemplateAttrsDO1> attrsDetail = getAttrsDetailOptimized(
                        attrsReqVO, deviceStatusMap, deviceReportMap, deviceOrderMap);

                vo.setAttrsDetail(attrsDetail);
                return vo;
            } catch (Exception e) {
                log.error("处理设备[{}]属性详情失败", fillDO.getDeviceId(), e);
                // 降级处理：返回空属性详情，避免整个分页失败
                IotOpeationFillWithAttrsVO vo = BeanUtils.toBean(fillDO, IotOpeationFillWithAttrsVO.class);
                vo.setAttrsDetail(Collections.emptyList());
                return vo;
            }
        }).collect(Collectors.toList());

        // 5. 构建返回结果
        PageResult<IotOpeationFillWithAttrsVO> pageResult = new PageResult<>(resultList, fillPage.getTotal());
        return success(pageResult);
    }

    /**
     * 优化后的属性详情查询：批量查询+缓存复用+减少冗余计算
     */
    private List<IotModelTemplateAttrsDO1> getAttrsDetailOptimized(
            IotModelTemplateAttrsRespVO vo,
            Map<String, YfDeviceDO> deviceStatusMap,
            Map<Long, Integer> deviceReportMap,
            Map<Long, IotOpeationFillDO> deviceOrderMap) throws SQLException {

        Long deviceId = vo.getDeviceId();
        String deviceCode = vo.getDeviceCode();
        LocalDate createDate = vo.getCreateTime();

        // 1. 复用批量查询结果（避免重复数据库查询）
        Integer isReport = deviceReportMap.getOrDefault(deviceId, 0);
        IotOpeationFillDO fillDO2 = deviceOrderMap.get(deviceId);
        YfDeviceDO yfDevice = deviceStatusMap.get(deviceCode);
        boolean isVirtualDevice = yfDevice != null && yfDevice.getStatus() == 3;

        // 2. 批量查询属性模板（一次查询）
        List<IotModelTemplateAttrsDO> attrsList = iotOpeationFillService.getAttrsByIdBatch(
                Collections.singletonList(vo)); // 可扩展为多设备批量查询

        if (CollectionUtils.isEmpty(attrsList)) {
            return Collections.emptyList();
        }

        // 3. 按isReport分支处理（优化数据查询逻辑）
        if (isReport != null && isReport == 1) {
            handleReportDeviceAttrs(attrsList, fillDO2);
        } else {
            handleNormalDeviceAttrs(attrsList, vo, isVirtualDevice, createDate);
        }

        // 4. 分组处理（提前分组，避免重复流处理）
        List<IotModelTemplateAttrsDO> sumList = new ArrayList<>();
        List<IotModelTemplateAttrsDO> nonSumList = new ArrayList<>();
        for (IotModelTemplateAttrsDO attrsDO : attrsList) {
            if (attrsDO.getIsSum() == 1) {
                sumList.add(attrsDO);
            } else {
                nonSumList.add(attrsDO);
            }
        }

        // 5. 构建结果（减少对象创建）
        IotModelTemplateAttrsDO1 resultDO = new IotModelTemplateAttrsDO1();
        resultDO.setSumList(sumList);
        resultDO.setNonSumList(nonSumList);
        return Collections.singletonList(resultDO);
    }

    /**
     * 处理虚拟设备（isReport=1）的属性详情
     */
    private void handleReportDeviceAttrs(List<IotModelTemplateAttrsDO> attrsList, IotOpeationFillDO fillDO2) throws SQLException {
        if (fillDO2 == null) {
            attrsList.forEach(attrsDO -> {
                attrsDO.setFillContent("");
                attrsDO.setIsCollection(0);
                attrsDO.setIsSum(0);
            });
            return;
        }

        // 批量查询reportList和reportList1（一次查询，避免循环）
        List<IotOpeationFillDO> reportList = iotOpeationFillService.reportList2(fillDO2);
        List<IotOpeationFillDO> reportList1 = iotOpeationFillService.reportList1(fillDO2);

        // 构建属性名到数据的映射（提前分组，避免重复stream过滤）
        Map<String, List<IotOpeationFillDO>> reportDataMap = reportList.stream()
                .collect(Collectors.groupingBy(IotOpeationFillDO::getOrgName));
        Map<String, List<IotOpeationFillDO>> reportDataMap1 = reportList1.stream()
                .collect(Collectors.groupingBy(IotOpeationFillDO::getOrgName));

        // 批量收集需要查询的runLog参数
        List<IotDeviceRunLogDO> runLogQueries = new ArrayList<>();
        reportList.forEach(reportData -> {
            IotDeviceRunLogDO query = new IotDeviceRunLogDO();
            query.setDeviceId(reportData.getDeviceId());
            query.setPointName(reportData.getOrgName());
            query.setCreateTime(reportData.getCreateTime());
            //query.setExt1(reportData.getOrgName()); // 存储orgName用于后续映射
            runLogQueries.add(query);
        });

        // 批量查询runLog数据（一次查询，替代循环查询）
        Map<String, String> runLogFillContentMap = new HashMap<>();
        if (!runLogQueries.isEmpty()) {
            List<IotDeviceRunLogDO> runLogList = iotOpeationFillService.batchReportData(runLogQueries);
            runLogFillContentMap = runLogList.stream()
                    .collect(Collectors.toMap(
                            logDO -> logDO.getPointName(), // orgName
                            logDO -> logDO.getFillContent() != null ? logDO.getFillContent() : "",
                            (v1, v2) -> v1 // 冲突时取第一个
                    ));
        }

        // 处理属性数据
        for (IotModelTemplateAttrsDO attrsDO : attrsList) {
            String attrName = attrsDO.getName();
            List<IotOpeationFillDO> cxList = reportDataMap.getOrDefault(attrName, Collections.emptyList());
            List<IotOpeationFillDO> cxList1 = reportDataMap1.getOrDefault(attrName, Collections.emptyList());

            // 处理reportList数据（累加逻辑）
            if (!cxList.isEmpty()) {
                double total = 0;
                for (IotOpeationFillDO reportData : cxList) {
                    String content = runLogFillContentMap.getOrDefault(reportData.getOrgName(), "");
                    total += safeParseInt(content);
                }
                attrsDO.setFillContent(total == 0 ? "" : String.valueOf(total));
            }

            // 处理reportList1数据（覆盖逻辑）
            if (!cxList1.isEmpty()) {
                IotOpeationFillDO reportData = cxList1.get(0); // 取第一条（原逻辑未处理多条，这里保持一致）
                String content = runLogFillContentMap.getOrDefault(reportData.getOrgName(), "");
                attrsDO.setFillContent(content);
            }

            attrsDO.setIsCollection(0);
            attrsDO.setIsSum(0);
        }
    }

    /**
     * 处理普通设备（isReport!=1）的属性详情
     */
    private void handleNormalDeviceAttrs(List<IotModelTemplateAttrsDO> attrsList,
                                         IotModelTemplateAttrsRespVO vo,
                                         boolean isVirtualDevice,
                                         LocalDate createDate) throws SQLException {

        Long deviceId = vo.getDeviceId();
        String deviceCode = vo.getDeviceCode();

        // 构建时间参数（一次计算，全局复用）
        /*LocalDateTime start = LocalDateTime.of(createDate, LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(createDate, LocalTime.MAX);
        Timestamp startTime = Timestamp.valueOf(start);
        Timestamp endTime = Timestamp.valueOf(end);*/

        // 定义下午4点的 LocalTime（16:00:00）
        LocalTime fourPm = LocalTime.of(16, 0, 0);

        // startTime：vo.getCreateTime() 的下午4点（当天16:00:00）
        LocalDateTime start = LocalDateTime.of(vo.getCreateTime(), fourPm);


        // endTime：vo.getCreateTime() 的前一天下午4点（前一天16:00:00）
        // 步骤：1. 先获取前一天的日期 2. 拼接下午4点的时间
        LocalDate previousDay = vo.getCreateTime().minusDays(1);
        LocalDateTime end = LocalDateTime.of(previousDay, fourPm);
        Timestamp startTime = Timestamp.valueOf(end);
        Timestamp endTime = Timestamp.valueOf(start);

        LocalDateTime midDay = LocalDateTime.of(createDate, LocalTime.of(12, 0));

        // 批量收集DeviceVO查询参数
        List<DeviceTdVO> deviceVOQueries = new ArrayList<>();
        List<IotDeviceRunLogDO> logDOQueries = new ArrayList<>();
        for (IotModelTemplateAttrsDO attrsDO : attrsList) {
            if (isVirtualDevice) {
                DeviceTdVO dv = new DeviceTdVO();
                dv.setDeviceName(deviceCode.toLowerCase());
                dv.setDeviceName1(deviceCode);
                dv.setColName(attrsDO.getModelAttr());
                dv.setTs(startTime);
                dv.setTs1(endTime);
                //dv.setExt1(attrsDO.getId().toString()); // 存储属性ID用于映射
                deviceVOQueries.add(dv);
            }

            IotDeviceRunLogDO logDO = new IotDeviceRunLogDO();
            logDO.setDeviceId(deviceId);
            logDO.setPointName(attrsDO.getName());
            logDO.setCreateTime(midDay);
            //logDO.setExt1(attrsDO.getId().toString()); // 存储属性ID用于映射
            logDOQueries.add(logDO);
        }

        // 批量查询（替代循环查询）
        Map<String, DeviceTdVO> deviceVOMap = new HashMap<>();
        /*if (isVirtualDevice && !deviceVOQueries.isEmpty()) {
            List<DeviceTdVO> deviceVOList = iDeviceService.batchGetYesInfo(deviceVOQueries);
            deviceVOMap = deviceVOList.stream()
                    .filter(voObj -> !StringUtils.isEmpty(voObj.getEarliestData()) && !"0.0".equals(voObj.getEarliestData()))
                    .collect(Collectors.toMap(DeviceTdVO::getDeviceName, Function.identity()));
        }*/


        if (isVirtualDevice && !deviceVOQueries.isEmpty()) {
            List<DeviceTdVO> deviceVOList = iDeviceService.batchGetYesInfo(deviceVOQueries);
            if(deviceVOList.size()>0){

                deviceVOMap = deviceVOList.stream()
                        // 增强过滤：排除deviceName为null、earliestData为null/空/0.0的记录
                        .filter(voObj -> {
                            // 过滤deviceName为null/空的情况
                            if (StringUtils.isEmpty(voObj.getColName())) {
                                return false;
                            }
                            // 过滤earliestData为null/空/0.0的情况
                            String earliest = voObj.getEarliestData();
                            return earliest != null && !earliest.isEmpty() && !"0.0".equals(earliest);
                        })
                        // 使用重载方法：key重复时保留后面的记录（或根据业务选择保留前面的）
                        .collect(Collectors.toMap(
                                DeviceTdVO::getColName,  // key：deviceName
                                Function.identity(),       // value：自身
                                (v1, v2) -> v2             // 重复key时的合并策略（此处保留后一个）
                        ));
            }else{
                isVirtualDevice = false;
            }

        }

        // 批量查询logInfo和maxLog
        Map<String, IotDeviceRunLogDO> logInfoMap = new HashMap<>();
        Map<String, IotDeviceRunLogDO> maxLogMap = new HashMap<>();
        if (!logDOQueries.isEmpty()) {
            logInfoMap = iotOpeationFillService.batchGetLogInfo(logDOQueries).stream()
                    .collect(Collectors.toMap(IotDeviceRunLogDO::getPointName, Function.identity()));
            maxLogMap = iotOpeationFillService.batchGetMaxFillInfo(logDOQueries).stream()
                    .collect(Collectors.toMap(IotDeviceRunLogDO::getPointName, Function.identity()));
        }

        // 处理属性数据
        for (IotModelTemplateAttrsDO attrsDO : attrsList) {
            String attrId = attrsDO.getModelAttr();
            String attrName = attrsDO.getName();
            if (isVirtualDevice) {
                DeviceTdVO deviceVO = deviceVOMap.get(attrId);
                if (deviceVO != null) {
                    // 数采设备逻辑
                    double diff = Double.parseDouble(deviceVO.getLatestData()) - Double.parseDouble(deviceVO.getEarliestData());
                    //如果当日差值为0，则证明该设备虽然是数采，但累计有问题，执行非数采逻辑
                    if(diff==0.0){
                        unCollectionDev(logInfoMap, maxLogMap, attrsDO, attrName);
                    }else{
                        attrsDO.setFillContent(String.valueOf(diff));
                        attrsDO.setTotalRunTime(BigDecimal.valueOf(Double.parseDouble(deviceVO.getLatestData())));
                        attrsDO.setIsCollection(1);
                    }
                }else{
                    // 非数采设备逻辑
                    unCollectionDev(logInfoMap, maxLogMap, attrsDO, attrName);
                    /*IotDeviceRunLogDO logInfo = logInfoMap.get(attrName);
                    IotDeviceRunLogDO maxLog = maxLogMap.get(attrName);

                    if (logInfo != null) {
                        attrsDO.setFillContent(logInfo.getFillContent());
                        attrsDO.setTotalRunTime(logInfo.getTotalRunTime() != null ? logInfo.getTotalRunTime() : BigDecimal.ZERO);
                    } else {
                        attrsDO.setFillContent("");
                        attrsDO.setTotalRunTime(maxLog != null ? maxLog.getTotalRunTime() : BigDecimal.ZERO);
                    }
                    attrsDO.setIsCollection(0);*/
                }
            }else{
                // 非数采设备逻辑
                unCollectionDev(logInfoMap, maxLogMap, attrsDO, attrName);
                /*IotDeviceRunLogDO logInfo = logInfoMap.get(attrName);
                IotDeviceRunLogDO maxLog = maxLogMap.get(attrName);

                if (logInfo != null) {
                    attrsDO.setFillContent(logInfo.getFillContent());
                    attrsDO.setTotalRunTime(logInfo.getTotalRunTime() != null ? logInfo.getTotalRunTime() : BigDecimal.ZERO);
                } else {
                    attrsDO.setFillContent("");
                    attrsDO.setTotalRunTime(maxLog != null ? maxLog.getTotalRunTime() : BigDecimal.ZERO);
                }
                attrsDO.setIsCollection(0);*/
            }


        }
    }

    //非数采设备处理逻辑
    private void unCollectionDev(Map<String, IotDeviceRunLogDO> logInfoMap, Map<String, IotDeviceRunLogDO> maxLogMap, IotModelTemplateAttrsDO attrsDO, String attrName) {
        IotDeviceRunLogDO logInfo = logInfoMap.get(attrName);
        IotDeviceRunLogDO maxLog = maxLogMap.get(attrName);
        if (logInfo != null) {
            attrsDO.setFillContent(logInfo.getFillContent());
            attrsDO.setTotalRunTime(logInfo.getTotalRunTime() != null ? logInfo.getTotalRunTime() : BigDecimal.ZERO);
        } else {
            attrsDO.setFillContent("");
            attrsDO.setTotalRunTime(maxLog != null ? maxLog.getTotalRunTime() : BigDecimal.ZERO);
        }
        attrsDO.setIsCollection(0);
    }


    //**************






    @GetMapping("/orderPage")
    @Operation(summary = "获得运行记录填报分页")
    @PreAuthorize("@ss.hasPermission('rq:iot-opeation-fill:query')")
    public CommonResult<List<IotOpeationFillDO>> getOrderPage(@Valid IotOpeationFillRespVO pageReqVO) {
        List<IotOpeationFillDO> fillList = new ArrayList<>();
        /* if(pageReqVO.getDeviceId()!=null){
         *//**
         * 根据设备ID和OrderId返回
         *//*

        }else{*/
        fillList = iotOpeationFillService.fillListByDeptId(pageReqVO);


        return success(BeanUtils.toBean(fillList, IotOpeationFillDO.class));
    }




    @GetMapping("/fillRecordPage")
    @Operation(summary = "获得运行记录填报分页")
    public CommonResult<PageResult<IotOpeationFillOrderDO>> getFillRecords(@Valid IotOpeationFillPageReqVO pageReqVO) {

        return success(BeanUtils.toBean( iotOpeationFillService.fillRecords(pageReqVO), IotOpeationFillOrderDO.class));
    }

    @GetMapping("/planDevPage")
    @Operation(summary = "获得运行计划填报分页")
    public CommonResult<PageResult<IotDeviceRespVO>> getPlan(@Valid IotOpeationFillPageReqVO pageReqVO) {

        return success(BeanUtils.toBean( iotOpeationFillService.getFillDevices1(pageReqVO), IotDeviceRespVO.class));
    }



    @GetMapping("/countPage")
    @Operation(summary = "获得运行记录设备填报分页")
    public CommonResult<PageResult<IotDeviceCountData>> countPage(@Valid IotOpeationFillPageReqVO pageReqVO) {
        return success(BeanUtils.toBean( iotOpeationFillService.deviceCountList(pageReqVO), IotDeviceCountData.class));
    }

    @GetMapping("/getCount")
    @PermitAll
    @Operation(summary = "获得PMS 功能优化 设备模板属性")
    @Parameter(name = "deviceCategoryName", description = "名称", required = true, example = "1024")
    public CommonResult<IotCountListDO> getCountList(IotCountDataDO vo) throws SQLException{
        List<IotCountDataDO> list = iotOpeationFillService.countList(vo);
        List<IotCountDataDO> totalList = list.stream().filter(item->item.getDeptId().equals(vo.getDeptId())).collect(Collectors.toList());
        List<IotCountDataDO> deptCountList = list.stream().filter(item->!item.getDeptId().equals(vo.getDeptId())).collect(Collectors.toList());
        IotCountListDO listDO = new IotCountListDO();
        listDO.setTotalList(totalList);
        listDO.setDeptCountList(deptCountList);
        return success(BeanUtils.toBean(listDO,IotCountListDO.class));
    }

    @GetMapping("/getDeviceCount")
    @PermitAll
    @Operation(summary = "获得PMS 功能优化 设备模板属性")
    @Parameter(name = "deviceCategoryName", description = "名称", required = true, example = "1024")
    public CommonResult<IotCountListDO> getDeviceCount(IotCountDataDO vo) throws SQLException{
        List<IotCountDataDO> list = iotOpeationFillService.countDeviceList(vo);
        IotCountListDO listDO = new IotCountListDO();
        listDO.setTotalList(list);
        return success(BeanUtils.toBean(listDO,IotCountListDO.class));
    }

    @GetMapping("/prod/detail/{id}")
    @PermitAll
    @TenantIgnore
    @Operation(summary = "获得瑞鹰生产日报的生产明细")
    public CommonResult<List<IotRyDailyReportDetailRespVO>> getProdDetail(@PathVariable("id") Long id) {
        List<IotRyDailyReportDetailRespVO> details = new ArrayList<>();
        IotOpeationFillOrderDO iotOpeationFillOrderDO = iotOpeationFillOrderMapper.selectById(id);
        if (ObjUtil.isEmpty(iotOpeationFillOrderDO)) {
            success(details);
        }
        // 查询运行记录对应的日报id 因为 生产动态明细 日期可能填写非当天的数据
        String reportDateStr = StrUtil.EMPTY;
        if (ObjUtil.isNotEmpty(iotOpeationFillOrderDO.getCreateTime())) {
            reportDateStr = LocalDateTimeUtil.format(iotOpeationFillOrderDO.getCreateTime(), DatePattern.NORM_DATE_PATTERN);
        }
        IotOpeationFillDO report = iotOpeationFillService.selectRyFillReports(iotOpeationFillOrderDO.getDeptId(), reportDateStr);
        if (ObjUtil.isNotEmpty(report)) {
            details = iotRyDailyReportService.ryDailyReportDetails(null, iotOpeationFillOrderDO.getDeptId(), report.getReportId());
        }
        return success(details);
    }

    @GetMapping("/getAttrs")
    @PermitAll
    @Operation(summary = "获得PMS 功能优化 设备模板属性")
    @Parameter(name = "deviceCategoryName", description = "名称", required = true, example = "1024")
    public CommonResult<List<IotModelTemplateAttrsDO1>> getModelAttrs(@Valid IotModelTemplateAttrsRespVO vo) throws SQLException{

        //判断是否为虚拟设备
        //如果是走原来逻辑
        //不是走虚拟设备逻辑
        IotOpeationFillDO fillDO = new IotOpeationFillDO();
        fillDO.setDeviceId(vo.getDeviceId());
        fillDO.setCreateTime(vo.getCreateTime().atStartOfDay());
        IotOpeationFillDO fillDO1 = iotOpeationFillService.isReport(fillDO);


        List<IotModelTemplateAttrsDO1> resut = new ArrayList<>();
        List<IotModelTemplateAttrsDO> list = iotOpeationFillService.getAttrsById(vo );

        if(fillDO1.getIsReport() !=null && fillDO1.getIsReport()==1){

            IotOpeationFillDO fillDO2 = iotOpeationFillService.orderDO(fillDO);

            List<IotOpeationFillDO> reportList = new ArrayList<>();
            List<IotOpeationFillDO> reportList1 = new ArrayList<>();

            if(fillDO2!=null){
                reportList = iotOpeationFillService.reportList(fillDO2);
                reportList1 = iotOpeationFillService.reportList1(fillDO2);
            }


            for (IotModelTemplateAttrsDO attrsDO:list) {





                List<IotOpeationFillDO> cxLixt = reportList.stream().filter(e->e.getOrgName().equals(attrsDO.getName())).collect(Collectors.toList());
                //虚拟设备取值
                List<IotOpeationFillDO> cxLixt1 = reportList1.stream().filter(e->e.getOrgName().equals(attrsDO.getName())).collect(Collectors.toList());

                if(cxLixt.size()>0){
                    // 使用Map按orgName分组存储累加结果
                    Map<String, String> orgNameToFillContent = new HashMap<>();

                    for (IotOpeationFillDO reportData : cxLixt) {
                        IotDeviceRunLogDO report = new IotDeviceRunLogDO();
                        report.setDeviceId(reportData.getDeviceId());
                        report.setPointName(reportData.getOrgName());
                        report.setCreateTime(reportData.getCreateTime());

                        IotDeviceRunLogDO reportCx = iotOpeationFillService.reportData(report);

                        String currentContent = "";
                        if(reportCx==null){
                            attrsDO.setFillContent("");
                        }else{
                            currentContent = reportCx.getFillContent() != null ? reportCx.getFillContent() : "";
                        }


                        // 获取当前orgName
                        String orgName = reportData.getOrgName();

                        // 累加相同orgName的内容
                        if (orgNameToFillContent.containsKey(orgName)) {
                            String existingContent = orgNameToFillContent.get(orgName);

                            double existingValue = safeParseInt(existingContent);
                            double currentValue = safeParseInt(currentContent);

                            if((existingValue + currentValue)==0){
                                orgNameToFillContent.put(orgName, "");
                            }else{
                                orgNameToFillContent.put(orgName, String.valueOf(existingValue + currentValue));
                            }

                        } else {
                            orgNameToFillContent.put(orgName, currentContent);
                        }
                        attrsDO.setFillContent(orgNameToFillContent.get(reportData.getOrgName()));

                    }
                }

                if(cxLixt1.size()>0){
                    for (IotOpeationFillDO reportData : cxLixt1) {
                        IotDeviceRunLogDO report = new IotDeviceRunLogDO();
                        report.setDeviceId(reportData.getDeviceId());
                        report.setPointName(reportData.getOrgName());
                        report.setCreateTime(reportData.getCreateTime());
                        IotDeviceRunLogDO reportCx = iotOpeationFillService.reportData(report);

                        String currentContent = "";
                        if(reportCx!=null){
                            currentContent = reportCx.getFillContent() != null ? reportCx.getFillContent() : "";
                            attrsDO.setFillContent(currentContent);
                        }
                    }
                }


                attrsDO.setIsCollection(0);
                attrsDO.setIsSum(0);
            }



        }else{



            List<YfDeviceDO> allDevice = yfDeviceService.getAllDevice();



            /*LocalTime localTime = LocalTime.of(0,0,0);
            LocalTime localTime1 = LocalTime.of(23,59,59);

            LocalDateTime start = LocalDateTime.of(vo.getCreateTime(),localTime);
            LocalDateTime end = LocalDateTime.of(vo.getCreateTime(),localTime1);

            Timestamp startTime = Timestamp.valueOf(start);
            Timestamp endTime = Timestamp.valueOf(end);*/

            // 定义下午4点的 LocalTime（16:00:00）
            LocalTime fourPm = LocalTime.of(16, 0, 0);

            // startTime：vo.getCreateTime() 的下午4点（当天16:00:00）
            LocalDateTime start = LocalDateTime.of(vo.getCreateTime(), fourPm);


            // endTime：vo.getCreateTime() 的前一天下午4点（前一天16:00:00）
            // 步骤：1. 先获取前一天的日期 2. 拼接下午4点的时间
            LocalDate previousDay = vo.getCreateTime().minusDays(1);
            LocalDateTime end = LocalDateTime.of(previousDay, fourPm);
            Timestamp startTime = Timestamp.valueOf(end);
            Timestamp endTime = Timestamp.valueOf(start);


            List<YfDeviceDO> existList = allDevice.stream().filter(e->e.getStatus()==3).collect(Collectors.toList());
            boolean exists1 = existList.stream().anyMatch(yfDeviceDO->yfDeviceDO.getSerialNumber().equals(vo.getDeviceCode()));

            IotDeviceRunLogDO logDO1 = new IotDeviceRunLogDO();
            logDO1.setDeviceId(vo.getDeviceId());
            LocalTime local = LocalTime.of(12, 0);
            logDO1.setCreateTime(LocalDateTime.of(vo.getCreateTime(),local));

            if(exists1){
                for (IotModelTemplateAttrsDO attrsDO:list) {

                    DeviceVO dv= new DeviceVO();
                    dv.setDeviceName(vo.getDeviceCode().toLowerCase());
                    dv.setColName(attrsDO.getModelAttr());
                    dv.setTs(startTime);
                    dv.setTs1(endTime);

                    DeviceVO deviceVO = iDeviceService.getYesInfo(dv);

                    if(!StringUtils.isEmpty(deviceVO)){

                        double diff = Double.parseDouble(deviceVO.getLatestData()) - Double.parseDouble(deviceVO.getEarliestData());

                        if(diff==0.0){
                            extracted(logDO1, attrsDO);
                        }else{
                            attrsDO.setFillContent(String.valueOf(diff));
                            attrsDO.setTotalRunTime(BigDecimal.valueOf(Double.parseDouble(deviceVO.getLatestData())));
                            /**
                             * 设置为数采
                             */
                            attrsDO.setIsCollection(1);
                        }

                        /*attrsDO.setFillContent(
                                String.valueOf(Double.parseDouble(deviceVO.getLatestData())-Double.parseDouble(deviceVO.getEarliestData())));
                        attrsDO.setTotalRunTime(BigDecimal.valueOf(Double.parseDouble(deviceVO.getLatestData())));*/

                    }else{
                        /*logDO1.setPointName(attrsDO.getName());
                        IotDeviceRunLogDO logInfo = iotOpeationFillService.getLogInfo(logDO1);
                        IotDeviceRunLogDO maxLog = iotOpeationFillService.getMaxFillInfo(logDO1);
                        if(!StringUtils.isEmpty(logInfo)){

                            attrsDO.setFillContent(logInfo.getFillContent());

                            if(StringUtils.isEmpty(maxLog)){
                                attrsDO.setTotalRunTime(BigDecimal.valueOf(0));
                            }else{
                                attrsDO.setTotalRunTime(maxLog.getTotalRunTime());
                            }
                            *//**
                             * 设置为非数采
                             *//*
                            attrsDO.setIsCollection(0);
                        }else{
                            attrsDO.setFillContent("");
                            if(StringUtils.isEmpty(maxLog)){
                                attrsDO.setTotalRunTime(BigDecimal.valueOf(0));
                            }else{
                                attrsDO.setTotalRunTime(maxLog.getTotalRunTime());
                            }
                            *//**
                             * 设置为非数采
                             *//*
                            attrsDO.setIsCollection(0);
                        }*/
                        extracted(logDO1, attrsDO);
                    }
                }
            }else{

                for (IotModelTemplateAttrsDO attrsDO:list) {
                    logDO1.setPointName(attrsDO.getName());
                    IotDeviceRunLogDO logInfo = iotOpeationFillService.getLogInfo(logDO1);
                    IotDeviceRunLogDO maxLog = iotOpeationFillService.getMaxFillInfo(logDO1);
                    if(!StringUtils.isEmpty(logInfo)){

                        attrsDO.setFillContent(logInfo.getFillContent());
                        attrsDO.setTotalRunTime(logInfo.getTotalRunTime());

                        /**
                         * 设置为非数采
                         */
                        attrsDO.setIsCollection(0);


                    }else{
                        attrsDO.setFillContent("");
                        if(StringUtils.isEmpty(maxLog)){
                            attrsDO.setTotalRunTime(BigDecimal.valueOf(0));
                        }else{
                            attrsDO.setTotalRunTime(maxLog.getTotalRunTime());
                        }

                        /**
                         * 设置为非数采
                         */
                        attrsDO.setIsCollection(0);

                    }

                }

            }





        }
        List<IotModelTemplateAttrsDO> sumList = list.stream().filter(e->e.getIsSum()==1).collect(Collectors.toList());
        List<IotModelTemplateAttrsDO> nonSumList = list.stream().filter(e->e.getIsSum()==0).collect(Collectors.toList());


        IotModelTemplateAttrsDO1 sum = new IotModelTemplateAttrsDO1();
        sum.setSumList(sumList);
        sum.setNonSumList(nonSumList);

        resut.add(sum);


        return success(BeanUtils.toBean(resut,IotModelTemplateAttrsDO1.class));
    }

    private void extracted(IotDeviceRunLogDO logDO1, IotModelTemplateAttrsDO attrsDO) {
        logDO1.setPointName(attrsDO.getName());
        IotDeviceRunLogDO logInfo = iotOpeationFillService.getLogInfo(logDO1);
        IotDeviceRunLogDO maxLog = iotOpeationFillService.getMaxFillInfo(logDO1);
        if(!StringUtils.isEmpty(logInfo)){

            attrsDO.setFillContent(logInfo.getFillContent());

            if(StringUtils.isEmpty(maxLog)){
                attrsDO.setTotalRunTime(BigDecimal.valueOf(0));
            }else{
                attrsDO.setTotalRunTime(maxLog.getTotalRunTime());
            }
            /**
             * 设置为非数采
             */
            attrsDO.setIsCollection(0);
        }else{
            attrsDO.setFillContent("");
            if(StringUtils.isEmpty(maxLog)){
                attrsDO.setTotalRunTime(BigDecimal.valueOf(0));
            }else{
                attrsDO.setTotalRunTime(maxLog.getTotalRunTime());
            }
            /**
             * 设置为非数采
             */
            attrsDO.setIsCollection(0);
        }
    }

    // 工具方法：将字符串转换为整数，空字符串视为0
    private double safeParseInt(String str) {
        if (str == null || str.trim().isEmpty()) {
            return 0;
        }
        try {
            return Integer.parseInt(str);
        } catch (NumberFormatException e) {
            // 如果字符串不是有效的整数格式，也返回0或根据实际需求处理
            return 0;
        }
    }

    @GetMapping("/getDeivceFillInfo")
    @PermitAll
    @Operation(summary = "获得PMS 功能优化 设备模板属性")
    @Parameter(name = "deviceCategoryName", description = "名称", required = true, example = "1024")
    public CommonResult<List<IotDeviceRunLogDO>> getDeivceFillInfo(@Valid IotDeviceRunLogDO vo) {
        List<IotDeviceRunLogDO> list = iotOpeationFillService.getDeivceFillInfo(vo);
        return success(BeanUtils.toBean(list,IotDeviceRunLogDO.class));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出运行记录填报 Excel")
    @PreAuthorize("@ss.hasPermission('rq:iot-opeation-fill:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportIotOpeationFillExcel(@Valid IotOpeationFillPageReqVO pageReqVO,
                                           HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<IotOpeationFillDO> list = iotOpeationFillService.getIotOpeationFillPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "运行记录填报.xls", "数据", IotOpeationFillRespVO.class,
                BeanUtils.toBean(list, IotOpeationFillRespVO.class));
    }


}