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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
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.pojo.Pms;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.pms.ThingsModelDTO;
import cn.iocoder.yudao.module.pms.controller.admin.TableDataInfo;
import cn.iocoder.yudao.module.pms.controller.admin.depttype.vo.IotDeptTypePageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.failure.vo.IotFailureReportPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.inspect.order.vo.IotInspectOrderPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.inspect.plan.vo.IotInspectPlanPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotdevicerunlog.vo.IotDeviceRunLogPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotdevicerunlog.vo.IotDeviceRunLogRespVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo.IotMainWorkOrderPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotopeationfill.vo.IotOpeationFillPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportTaskCountVO;
import cn.iocoder.yudao.module.pms.controller.admin.maintain.vo.IotMaintainPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.stat.vo.*;
import cn.iocoder.yudao.module.pms.controller.admin.vo.DeviceVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotProductClassifyListReqVO;
import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.IotProductClassifyDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.depttype.IotDeptTypeDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.failure.IotFailureReportDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.inspect.IotInspectOrderDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.inspect.IotInspectOrderDetailDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.inspect.IotInspectPlanDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotcountdata.IotCountDataDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorder.IotMainWorkOrderDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotoutbound.IotOutboundDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotrddailyreport.IotRdDailyReportDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotrhdailyreport.IotRhDailyReportDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotrydailyreport.IotRyDailyReportDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotsapstock.IotSapStockDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.maintain.IotMaintainDO;
import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.IotProductClassifyMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.TDDeviceMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.depttype.IotDeptTypeMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.failure.IotFailureReportMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.inspect.IotInspectOrderDetailMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.inspect.IotInspectOrderMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.inspect.IotInspectPlanMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotdevicerunlog.IotDeviceRunLogMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorder.IotMainWorkOrderMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotopeationfill.IotOpeationFillMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotoutbound.IotOutboundMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotrddailyreport.IotRdDailyReportMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotrhdailyreport.IotRhDailyReportMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotrydailyreport.IotRyDailyReportMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotsapstock.IotSapStockMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.maintain.IotMaintainMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.tdparams.IotTdParamsMapper;
import cn.iocoder.yudao.module.pms.service.DeviceServiceImpl;
import cn.iocoder.yudao.module.pms.service.inspect.IotInspectOrderService;
import cn.iocoder.yudao.module.pms.service.iotmainworkorder.IotMainWorkOrderService;
import cn.iocoder.yudao.module.pms.service.iotrydailyreport.IotRyDailyReportService;
import cn.iocoder.yudao.module.pms.service.maintain.IotMaintainService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
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.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.validation.Valid;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_DAILY_REPORT_DEPT_NOT_EXISTS;
import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_DAILY_REPORT_TIME_NOT_EXISTS;

@Tag(name = "统计接口")
@RestController
@RequestMapping("/rq/stat")
@Validated
public class IotStaticController {
    @Resource
    private IotFailureReportMapper iotFailureReportMapper;
    @Resource
    private IotMaintainMapper iotMaintainMapper;
    @Autowired
    private IotInspectOrderMapper iotInspectOrderMapper;
    @Autowired
    private IotInspectOrderService iotInspectOrderService;
    @Autowired
    private IotMainWorkOrderMapper iotMainWorkOrderMapper;
    @Autowired
    private DeviceServiceImpl deviceServiceImpl;
    @Autowired
    private IotDeviceMapper iotDeviceMapper;
    @Autowired
    private IotProductClassifyMapper iotProductClassifyMapper;
    @Autowired
    private DeptApi deptApi;
    @Autowired
    private AdminUserApi adminUserApi;
    @Autowired
    private IotSapStockMapper iotSapStockMapper;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private IotMaintainService iotMaintainService;
    @Value("${yanfan.url}")
    private String yanfanUrl;
    @Autowired
    private IotInspectOrderDetailMapper iotInspectOrderDetailMapper;
    @Autowired
    private DeptService deptService;
    @Autowired
    private IotOpeationFillMapper iotOpeationFillMapper;
    @Autowired
    private IotDeviceRunLogMapper iotDeviceRunLogMapper;
    @Autowired
    private TDDeviceMapper deviceMapper;
    @Autowired
    private IotOutboundMapper iotOutboundMapper;
    @Autowired
    private IotInspectPlanMapper iotInspectPlanMapper;
    @Autowired
    private IotRhDailyReportMapper iotRhDailyReportMapper;
    @Autowired
    private IotRyDailyReportService iotRyDailyReportService;
    @Autowired
    private IotRyDailyReportMapper iotRyDailyReportMapper;
    @Autowired
    private IotRdDailyReportMapper iotRdDailyReportMapper;
    @Resource
    private IotDeptTypeMapper iotDeptTypeMapper;
    @Autowired
    private DeptUtil deptUtil;
    @Autowired
    private IotMainWorkOrderService iotMainWorkOrderService;

    @GetMapping("/main/day")
    public CommonResult<Map<String, Object>> getMaintainDay() {
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(1);
        IotFailureReportPageReqVO iotFailureReportPageReqVO = new IotFailureReportPageReqVO();
        iotFailureReportPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        Long failure = iotFailureReportMapper.selectCountByTimeAndStatus(iotFailureReportPageReqVO);
        IotMaintainPageReqVO iotMaintainPageReqVO = new IotMaintainPageReqVO();
        iotMaintainPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        Long maintain = iotMaintainMapper.selectCountByTimeAndStatus(iotMaintainPageReqVO);
        return success(ImmutableMap.of("failureDay", failure, "maintainDay", maintain));
    }

    @GetMapping("/notice")
    @PermitAll
    public CommonResult<PageResult<OrderVo>> getNotice(@Valid OrderVo pageReqVO) {
        PageResult<OrderVo> notice = iotMaintainService.getNotice(pageReqVO);
        if (CollUtil.isEmpty(notice.getList())) {
            return success(new PageResult<>(notice.getTotal()));
        }
        return success(notice);
    }

    @GetMapping("/main/week")
    public CommonResult<Map<String, Object>> getMaintainWeek() {
        ImmutableMap<String, LocalDateTime> beginEndWeek = getBeginEndWeek();
        IotFailureReportPageReqVO iotFailureReportPageReqVO = new IotFailureReportPageReqVO();
        iotFailureReportPageReqVO.setCreateTime(new LocalDateTime[]{beginEndWeek.get("start"), beginEndWeek.get("end")});
        Long failure = iotFailureReportMapper.selectCountByTimeAndStatus(iotFailureReportPageReqVO);
        IotMaintainPageReqVO iotMaintainPageReqVO = new IotMaintainPageReqVO();
        iotMaintainPageReqVO.setCreateTime(new LocalDateTime[]{beginEndWeek.get("start"), beginEndWeek.get("end")});
        Long maintain = iotMaintainMapper.selectCountByTimeAndStatus(iotMaintainPageReqVO);
        return success(ImmutableMap.of("failureWeek", failure, "maintainWeek", maintain));
    }

    @GetMapping("/main/month")
    public CommonResult<Map<String, Object>> getMaintainMonth() {
        ImmutableMap<String, LocalDateTime> beginEndMonth = getBeginEndMonth();
        IotFailureReportPageReqVO iotFailureReportPageReqVO = new IotFailureReportPageReqVO();
        iotFailureReportPageReqVO.setCreateTime(new LocalDateTime[]{beginEndMonth.get("start"), beginEndMonth.get("end")});
        Long failure = iotFailureReportMapper.selectCountByTimeAndStatus(iotFailureReportPageReqVO);
        IotMaintainPageReqVO iotMaintainPageReqVO = new IotMaintainPageReqVO();
        iotMaintainPageReqVO.setCreateTime(new LocalDateTime[]{beginEndMonth.get("start"), beginEndMonth.get("end")});
        Long maintain = iotMaintainMapper.selectCountByTimeAndStatus(iotMaintainPageReqVO);
        return success(ImmutableMap.of("failureMonth", failure, "maintainMonth", maintain));
    }

    @GetMapping("/main/total")
    public CommonResult<Map<String, Object>> getMaintainTotal() {
        Long failure = iotFailureReportMapper.selectCount();
        Long maintain = iotMaintainMapper.selectCount();
            return success(ImmutableMap.of("failureTotal", failure, "maintainTotal", maintain));
    }

    @GetMapping("/main/status")
    public CommonResult<Map<String, Object>> getMaintainStatusInfo() {
        List<IotFailureReportDO> iotFailureReportDOS = iotFailureReportMapper.selectList();
        Map<String, Long> failure = iotFailureReportDOS.stream().collect(Collectors.groupingBy(IotFailureReportDO::getStatus, Collectors.counting()));
        List<IotMaintainDO> iotMaintainDOS = iotMaintainMapper.selectList();
        Map<String, Long> maintain = iotMaintainDOS.stream().collect(Collectors.groupingBy(IotMaintainDO::getStatus, Collectors.counting()));
        return success(ImmutableMap.of("failureStatus", failure, "maintainStatus", maintain));
    }

    @GetMapping("/main/year")
    public CommonResult<List<MonthRange>> getMaintainYear() {
        List<MonthRange> lastYearMonths = getLastYearMonthRanges();
        List<MonthRange> collect = lastYearMonths.stream().map(e -> {
            IotFailureReportPageReqVO iotFailureReportPageReqVO = new IotFailureReportPageReqVO();
            iotFailureReportPageReqVO.setCreateTime(new LocalDateTime[]{e.getStart(), e.getEnd()});
            Long l = iotFailureReportMapper.selectCountByTimeAndStatus(iotFailureReportPageReqVO);
            e.setCount(Integer.valueOf(String.valueOf(l)));
            return e;
        }).collect(Collectors.toList());

        return success(collect);
    }

    @GetMapping("/inspect/day")
    public CommonResult<Map<String, Object>> getInspectDay() {
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(1);
        IotInspectOrderPageReqVO iotInspectOrderPageReqVO = new IotInspectOrderPageReqVO();
        iotInspectOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        Long inspectDayTotal = iotInspectOrderMapper.selectCountByTimeAndStatus(iotInspectOrderPageReqVO);
        iotInspectOrderPageReqVO.setStatus("todo");
        Long inspectDayTodo = iotInspectOrderMapper.selectCountByTimeAndStatus(iotInspectOrderPageReqVO);

        return success(ImmutableMap.of("total", inspectDayTotal,"todo", inspectDayTodo));
    }

    @GetMapping("/inspect/week")
    public CommonResult<Map<String, Object>> getInspectWeek() {
        IotInspectOrderPageReqVO iotInspectOrderPageReqVO = new IotInspectOrderPageReqVO();
        ImmutableMap<String, LocalDateTime> beginEndWeek = getBeginEndWeek();
        iotInspectOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndWeek.get("start"), beginEndWeek.get("end")});
        Long inspectWeekTotal = iotInspectOrderMapper.selectCountByTimeAndStatus(iotInspectOrderPageReqVO);
        iotInspectOrderPageReqVO.setStatus("todo");
        Long inspectWeekTodo = iotInspectOrderMapper.selectCountByTimeAndStatus(iotInspectOrderPageReqVO);

        return success(ImmutableMap.of("total", inspectWeekTotal,"todo", inspectWeekTodo));
    }

    @GetMapping("/inspect/month")
    public CommonResult<Map<String, Object>> getInspectMonth() {
        IotInspectOrderPageReqVO iotInspectOrderPageReqVO = new IotInspectOrderPageReqVO();
        ImmutableMap<String, LocalDateTime> beginEndMonth = getBeginEndMonth();
        iotInspectOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndMonth.get("start"), beginEndMonth.get("end")});
        Long inspectWeekTotal = iotInspectOrderMapper.selectCountByTimeAndStatus(iotInspectOrderPageReqVO);
        iotInspectOrderPageReqVO.setStatus("todo");
        Long inspectWeekTodo = iotInspectOrderMapper.selectCountByTimeAndStatus(iotInspectOrderPageReqVO);

        return success(ImmutableMap.of("total", inspectWeekTotal,"todo", inspectWeekTodo));
    }

    @GetMapping("/inspect/total")
    public CommonResult<Map<String, Object>> getInspectTotal() {
        Long total = iotInspectOrderMapper.selectCount();
        Long todo = iotInspectOrderMapper.selectCount("status", "todo");

        return success(ImmutableMap.of("total", total,"todo", todo));
    }


    @GetMapping("/inspect/status")
    public CommonResult<Map<String, Long>> getInspectStatusInfo(IotCountDataDO vo) {
        Set<Long> ids = new HashSet<>();
        if (Objects.nonNull(vo.getDeptId())) {
            ids = deptService.getChildDeptIdListFromCache(vo.getDeptId());
            ids.add(vo.getDeptId());
        }
        List<IotInspectOrderDO> iotInspectOrderDOS = iotInspectOrderMapper.selectListStat(vo, ids);
        Map<String, Long> order = iotInspectOrderDOS.stream().collect(Collectors.groupingBy(IotInspectOrderDO::getStatus, Collectors.counting()));
        return success(order);
    }

    @GetMapping("/report/inspect/status")
    public CommonResult<Map<String, Long>> getInspectStatusInfoReport(IotCountDataDO vo) {
        Set<Long> ids;
        if (Objects.isNull(vo.getDeptId())){
            Long loginUserDeptId = SecurityFrameworkUtils.getLoginUserDeptId();
            String companyCode = deptUtil.getCompanyCode(loginUserDeptId);
            ids = deptUtil.getDeptIds(companyCode);
        } else {
            ids = deptService.getChildDeptIdListFromCache(vo.getDeptId());
            ids.add(vo.getDeptId());
        }
        Long todo = iotInspectOrderMapper.selectCount(vo, ids,"todo");
        Long finished = iotInspectOrderMapper.selectCount(vo, ids,"finished");
        Long ignore = iotInspectOrderMapper.selectCount(vo, ids,"ignore");
//        Map<String, Long> order = iotInspectOrderDOS.stream().collect(Collectors.groupingBy(IotInspectOrderDO::getStatus, Collectors.counting()));
        return success(ImmutableMap.of("todo",todo,"finished",finished,"ignore",ignore));
    }

    @GetMapping("/inspect/statuss/{dept}")
    public CommonResult<Map<String, Long>> getInspectStatusInfos(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        IotCountDataDO vo = new IotCountDataDO();
        List<IotInspectOrderDO> iotInspectOrderDOS = iotInspectOrderMapper.selectListStat(vo, ids);
        Map<String, Long> order = iotInspectOrderDOS.stream().collect(Collectors.groupingBy(IotInspectOrderDO::getStatus, Collectors.counting()));
        return success(order);
    }

    @GetMapping("/inspect/today/status")
    public CommonResult<Map<String, Long>> getInspectTodayStatusInfo() {
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(0);
        IotInspectOrderPageReqVO iotInspectOrderPageReqVO = new IotInspectOrderPageReqVO();
        iotInspectOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        List<IotInspectOrderDO> iotInspectOrderDOS = iotInspectOrderMapper.selectListByCreateTime(iotInspectOrderPageReqVO, new HashSet<>());
        Map<String, Long> order = iotInspectOrderDOS.stream().collect(Collectors.groupingBy(IotInspectOrderDO::getStatus, Collectors.counting()));
        return success(order);
    }

    @GetMapping("/inspect/year")
    public CommonResult<List<MonthRange>> getInspectYear() {
        List<MonthRange> lastYearMonths = getLastYearMonthRanges();
        List<MonthRange> collect = lastYearMonths.stream().map(e -> {
            IotInspectOrderPageReqVO iotInspectOrderPageReqVO = new IotInspectOrderPageReqVO();
            iotInspectOrderPageReqVO.setCreateTime(new LocalDateTime[]{e.getStart(), e.getEnd()});
            Long l = iotInspectOrderMapper.selectCountByTimeAndStatus(iotInspectOrderPageReqVO);
            e.setCount(Integer.valueOf(String.valueOf(l)));
            return e;
        }).collect(Collectors.toList());

        return success(collect);
    }


    @GetMapping("/maintenance/day")
    public CommonResult<Map<String, Object>> getMaintenanceDay() {
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(1);
        IotMainWorkOrderPageReqVO iotMainWorkOrderPageReqVO = new IotMainWorkOrderPageReqVO();
        iotMainWorkOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        Long inspectDayTotal = iotMainWorkOrderMapper.selectCountByTimeAndStatus(iotMainWorkOrderPageReqVO);
        iotMainWorkOrderPageReqVO.setResult(1);
        Long inspectDayTodo = iotMainWorkOrderMapper.selectCountByTimeAndStatus(iotMainWorkOrderPageReqVO);

        return success(ImmutableMap.of("total", inspectDayTotal,"todo", inspectDayTodo));
    }

    @GetMapping("/maintenance/week")
    public CommonResult<Map<String, Object>> getMaintenanceWeek() {
        IotMainWorkOrderPageReqVO iotMainWorkOrderPageReqVO = new IotMainWorkOrderPageReqVO();
        ImmutableMap<String, LocalDateTime> beginEndWeek = getBeginEndWeek();
        iotMainWorkOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndWeek.get("start"), beginEndWeek.get("end")});
        Long inspectWeekTotal = iotMainWorkOrderMapper.selectCountByTimeAndStatus(iotMainWorkOrderPageReqVO);
        iotMainWorkOrderPageReqVO.setResult(1);
        Long inspectWeekTodo = iotMainWorkOrderMapper.selectCountByTimeAndStatus(iotMainWorkOrderPageReqVO);

        return success(ImmutableMap.of("total", inspectWeekTotal,"todo", inspectWeekTodo));
    }

    @GetMapping("/maintenance/month")
    public CommonResult<Map<String, Object>> getMaintenanceMonth() {
        IotMainWorkOrderPageReqVO iotMainWorkOrderPageReqVO = new IotMainWorkOrderPageReqVO();
        ImmutableMap<String, LocalDateTime> beginEndMonth = getBeginEndMonth();
        iotMainWorkOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndMonth.get("start"), beginEndMonth.get("end")});
        Long inspectWeekTotal = iotMainWorkOrderMapper.selectCountByTimeAndStatus(iotMainWorkOrderPageReqVO);
        iotMainWorkOrderPageReqVO.setResult(1);
        Long inspectWeekTodo = iotMainWorkOrderMapper.selectCountByTimeAndStatus(iotMainWorkOrderPageReqVO);

        return success(ImmutableMap.of("total", inspectWeekTotal,"todo", inspectWeekTodo));
    }

    @GetMapping("/maintenance/total")
    public CommonResult<Map<String, Object>> getMaintenanceTotal() {
        Long total = iotMainWorkOrderMapper.selectCount();
        Long todo = iotMainWorkOrderMapper.selectCount("result", 1);

        return success(ImmutableMap.of("total", total,"todo", todo));
    }

    @GetMapping("/maintenance/status/{dept}")
    public CommonResult<Map<String, Long>> getMaintenanceStatusInfo(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        IotMainWorkOrderPageReqVO reqVO = new IotMainWorkOrderPageReqVO();
        reqVO.setDeptIds(ids);
        List<IotMainWorkOrderDO> iotMainWorkOrderDOS = iotMainWorkOrderMapper.selectList(reqVO);
        Map<Integer, Long> order = iotMainWorkOrderDOS.stream().collect(Collectors.groupingBy(IotMainWorkOrderDO::getResult, Collectors.counting()));
        Map<String, Long> resultMap = new HashMap<>(order.size());
        order.forEach((k,v)->{
            if (k==1) {
                resultMap.put("todo", v);
            }else if (k==2) {
                resultMap.put("finished", v);
            }
        });
        return success(resultMap);
    }

    @GetMapping("/maintenance/today/status")
    public CommonResult<Map<String, Long>> getMaintenanceTodayStatusInfo() {
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(0);
        IotMainWorkOrderPageReqVO iotMainWorkOrderPageReqVO = new IotMainWorkOrderPageReqVO();
        iotMainWorkOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        List<IotMainWorkOrderDO> iotInspectOrderDOS = iotMainWorkOrderMapper.selectListByCreateTime(iotMainWorkOrderPageReqVO, new HashSet<>());
        Map<Integer, Long> order = iotInspectOrderDOS.stream().collect(Collectors.groupingBy(IotMainWorkOrderDO::getResult, Collectors.counting()));
        Map<String, Long> resultMap = new HashMap<>(order.size());
        order.forEach((k,v)->{
            if (k==1) {
                resultMap.put("todo", v);
            }else if (k==2) {
                resultMap.put("finished", v);
            }
        });
        return success(resultMap);
    }

    @GetMapping("/maintenance/type")
    public CommonResult<Map<String, Long>> getMaintenanceType() {
        List<IotMainWorkOrderDO> iotMainWorkOrderDOS = iotMainWorkOrderMapper.selectList();
        Map<Integer, Long> order = iotMainWorkOrderDOS.stream().collect(Collectors.groupingBy(IotMainWorkOrderDO::getType, Collectors.counting()));
        Map<String, Long> resultMap = new HashMap<>(order.size());
        order.forEach((k,v)->{
            if (k==1) {
                resultMap.put("计划生成", v);
            }else if (k==2) {
                resultMap.put("临时新建", v);
            }
        });
        return success(resultMap);
    }

    @Resource
    private TDDeviceMapper tdDeviceMapper;
    @GetMapping("/td/chart/{deviceName}/{identifier}")
    public CommonResult<List<DeviceVO>> getTdChart(@PathVariable("deviceName") String deviceName, @PathVariable("identifier") String identifier, @RequestParam("beginTime") String beginTime, @RequestParam("endTime") String endTime) {
        if (StringUtils.isBlank(identifier)) {
            return null;
        }
        Timestamp start1 = generateTimestamp(beginTime);
        Timestamp end1 = generateTimestamp(endTime);
        Integer i = deviceMapper.tableIfExist(deviceName.toLowerCase());
        if (i==1) {
            List<DeviceVO> deviceVOS = tdDeviceMapper.selectAllBtTimeAndIdentifier(deviceName.toLowerCase(), identifier, start1, end1);
            deviceVOS.forEach(deviceVO->{
                deviceVO.setTimestamp(deviceVO.getTs().getTime());
                deviceVO.setValue(Objects.nonNull(deviceVO.getLogValue())?Double.valueOf(deviceVO.getLogValue()):null);
            });
            return success(deviceVOS.stream().sorted(Comparator.comparing(DeviceVO::getTimestamp).reversed()).collect(Collectors.toList()));
        } else {
            List<DeviceVO> deviceVOS = new ArrayList<>();
            return success(deviceVOS);
        }
    }
    @GetMapping("/td/chart/ly/{deviceName}/{identifier}")
    public CommonResult<List<DeviceVO>> getLyTdChart(@PathVariable("deviceName") String deviceName, @PathVariable("identifier") String identifier, @RequestParam("beginTime") String beginTime, @RequestParam("endTime") String endTime) {
        if (StringUtils.isBlank(identifier)) {
            return null;
        }
        Timestamp start1 = generateTimestamp(beginTime);
        Timestamp end1 = generateTimestamp(endTime);
        Integer i = deviceMapper.tableIfExist(deviceName.toLowerCase());
        if (i==1) {
            List<DeviceVO> deviceVOS = tdDeviceMapper.selectAllBtTimeAndIdentifierNoInterval(deviceName.toLowerCase(), identifier, start1, end1);
            deviceVOS.forEach(deviceVO->{
                deviceVO.setTimestamp(deviceVO.getTs().getTime());
                deviceVO.setValue(Objects.nonNull(deviceVO.getLogValue())?Double.valueOf(deviceVO.getLogValue()):null);
            });
            return success(deviceVOS.stream().sorted(Comparator.comparing(DeviceVO::getTimestamp).reversed()).collect(Collectors.toList()));
        } else {
            List<DeviceVO> deviceVOS = new ArrayList<>();
            return success(deviceVOS);
        }
    }

    @Autowired
    private IotTdParamsMapper iotTdParamsMapper;
    @GetMapping("/td/ly/chart")
    public CommonResult<ImmutableMap> getTdChartLy( @RequestParam("pageSize") Integer pageSize, @RequestParam("deviceCode") String deviceCode, @RequestParam(value = "identifier", required = false) String identifier,
                                                   @RequestParam("beginTime") String beginTime, @RequestParam("endTime") String endTime) {
        List<IotDeviceDO> iotDeviceDOS = iotDeviceMapper.selectByCodeIn(Collections.singleton(deviceCode));
        if (CollUtil.isEmpty(iotDeviceDOS)) {
            throw new ServiceException(new ErrorCode(111,"不存在设备"));
        }
        IotDeviceDO iotDeviceDO = iotDeviceDOS.get(0);
        TableDataInfo tableDataInfo = restTemplate.getForObject(yanfanUrl + "/prod-api/iot/device/listThingsModel?deviceId="+iotDeviceDO.getYfDeviceId()+"&pageNum=1&pageSize=200", TableDataInfo.class);
        if (tableDataInfo == null) {
            throw new ServiceException(new ErrorCode(111,"不存在数采属性"));
        }
        List<ThingsModelDTO> rows = JSON.parseArray(JSON.toJSONString(tableDataInfo.getRows()), ThingsModelDTO.class);
        Timestamp start1 = generateTimestamp(beginTime);
        Timestamp end1 = generateTimestamp(endTime);
        Integer i = deviceMapper.tableIfExist(deviceCode.toLowerCase());
        if (i==1) {
            if (StringUtils.isNotBlank(identifier)&&!"undefined".equals(identifier)) {
                List<DeviceVO> deviceVOS = tdDeviceMapper.selectAllBtTimeAndidentifierAll(deviceCode.toLowerCase(), identifier, start1, end1,pageSize);
                deviceVOS.forEach(deviceVO->{
                    deviceVO.setTimestamp(deviceVO.getTs().getTime());
                    deviceVO.setValue(Objects.nonNull(deviceVO.getLogValue())?Double.valueOf(deviceVO.getLogValue()):null);
                    rows.stream().filter(e -> e.getIdentifier().equals(deviceVO.getIdentity())).findFirst().ifPresent(deviceVO1->{
                        deviceVO.setIdentity(deviceVO1.getModelName());
                    });
                    deviceVO.setSerialNumber(deviceCode);
                    deviceVO.setDeviceName(iotDeviceDO.getDeviceName());
                });
                List<DeviceVO> collect = deviceVOS.stream().sorted(Comparator.comparing(DeviceVO::getTimestamp).reversed()).collect(Collectors.toList());
                return success(ImmutableMap.of( "data",collect));
            } else {
                List<DeviceVO> deviceVOS = tdDeviceMapper.selectAllBtTime(deviceCode.toLowerCase(), start1, end1, pageSize);
                deviceVOS.forEach(deviceVO->{
                    deviceVO.setTimestamp(deviceVO.getTs().getTime());
                    deviceVO.setValue(Objects.nonNull(deviceVO.getLogValue())?Double.valueOf(deviceVO.getLogValue()):null);
                    rows.stream().filter(e -> e.getIdentifier().equals(deviceVO.getIdentity())).findFirst().ifPresent(deviceVO1->{
                        deviceVO.setIdentity(deviceVO1.getModelName());
                    });
                    deviceVO.setSerialNumber(deviceCode);
                    deviceVO.setDeviceName(iotDeviceDO.getDeviceName());
                });
                List<DeviceVO> collect = deviceVOS.stream().sorted(Comparator.comparing(DeviceVO::getTimestamp).reversed()).collect(Collectors.toList());
                return success(ImmutableMap.of( "data",collect));
            }

        } else {
            List<DeviceVO> deviceVOS = new ArrayList<>();
            return success(ImmutableMap.of( "data",deviceVOS));
        }
    }

    public Set<Long> getDeptIds(String dept) {
        Set<Long> ids = new HashSet<>();
        List<DeptRespDTO> depts = new ArrayList<>();
        if ("rd".equals(dept)) {
            depts = deptApi.getDeptByName("四川瑞都");
        } else if ("rh".equals(dept)) {
            depts = deptApi.getDeptByName("瑞恒兴域");
        } else if ("ry".equals(dept)) {
            depts = deptApi.getDeptByName("瑞鹰国际");
        } else if ("yf".equals(dept)) {
            depts = deptApi.getDeptByName("科瑞石油技术");
        } else {
            Long loginUserDeptId = SecurityFrameworkUtils.getLoginUserDeptId();
            DeptRespDTO dto = deptApi.getDept(loginUserDeptId);
            depts = deptApi.getDeptByName(dto.getName());
        }
        if (CollUtil.isNotEmpty(depts)) {
            Long deptId = depts.get(0).getId();
            if (Objects.nonNull(depts.get(0).getId())) {
                ids = deptService.getChildDeptIdListFromCache(depts.get(0).getId());
                ids.add(deptId);
            }
        }
        return  ids;
    }

    @GetMapping("/home/device/count/{dept}")
    public CommonResult<ImmutableMap<Object, Object>> getHomeDeviceCountStat(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        Long deviceCount = iotDeviceMapper.selectByDept(ids);
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(0);
        IotDevicePageReqVO iotDevicePageReqVO = new IotDevicePageReqVO();
        iotDevicePageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        Long deviceToday = iotDeviceMapper.selectCountByTimeAndStatus(iotDevicePageReqVO);
        return success(ImmutableMap.of("total", deviceCount,"today", deviceToday));
    }

    /**
     * 查询所有瑞鹰 钻井 进尺 修井完成总井口数
     * @return
     */
    @GetMapping("/home/ry/count/zjxj")
    public CommonResult<ImmutableMap<Object, Object>> getHomeZjXjStat(IotRyDailyReportPageReqVO reqVO) {
        // 查询所有钻井进尺
        IotRyDailyReportPageReqVO zjReqVO = new IotRyDailyReportPageReqVO();
        zjReqVO.setProjectClassification("1");
        zjReqVO.setCreateTime(reqVO.getCreateTime());
        BigDecimal totalFootage = BigDecimal.ZERO;
        List<IotRyDailyReportDO> dailyReports = iotRyDailyReportMapper.dailyReports(zjReqVO);
        // 使用Stream API计算总进尺
        if (CollUtil.isNotEmpty(dailyReports)) {
            totalFootage = dailyReports.stream()
                    .map(IotRyDailyReportDO::getDailyFootage)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        }

        // 查询所有完工井数
        IotRyDailyReportPageReqVO xjReqVO = new IotRyDailyReportPageReqVO();
        xjReqVO.setCreateTime(reqVO.getCreateTime());
        List<IotRyDailyReportTaskCountVO> repairDeptTasks = iotRyDailyReportMapper.countRepairTasksByDept(xjReqVO);
        // Java8 Stream 简洁累加（核心优化）
        Integer completeWellCount = repairDeptTasks.stream()
                // 过滤null元素，避免空指针
                .filter(Objects::nonNull)
                // 转换为int流，处理属性为null的情况（null则取0）
                .mapToInt(task -> Optional.ofNullable(task.getCompletedTaskCount()).orElse(0))
                // 累加求和（空集合时sum()返回0，无需手动判空）
                .sum();

        return success(ImmutableMap.of("zj", totalFootage,"xj", completeWellCount));
    }

    @GetMapping("/home/maintain/count/{dept}")
    public CommonResult<ImmutableMap<Object, Object>> getHomeMaintainCountStat(@PathVariable("dept") String dept) {
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(0);
        Set<Long> ids = getDeptIds(dept);

        Long maintainCount = iotMaintainMapper.selectByDept(ids);
        IotMaintainPageReqVO iotMaintainPageReqVO = new IotMaintainPageReqVO();
        iotMaintainPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        Long maintainToday = iotMaintainMapper.selectCountByTimeAndStatus(iotMaintainPageReqVO);
        return success(ImmutableMap.of("total", maintainCount, "today", maintainToday));
    }

    @GetMapping("/home/work/count")
    public CommonResult<ImmutableMap<Object, Object>> getHomeWorkCountStat() {
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(0);
        Long workCount = iotMainWorkOrderMapper.selectCount();
        IotMainWorkOrderPageReqVO iotMainWorkOrderPageReqVO = new IotMainWorkOrderPageReqVO();
        iotMainWorkOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        Long workToday = iotMainWorkOrderMapper.selectCountByTimeAndStatus(iotMainWorkOrderPageReqVO);
        return success(ImmutableMap.of("total", workCount, "today", workToday));
    }

    @GetMapping("/home/inspect/count")
    public CommonResult<ImmutableMap<Object, Object>> getHomeInspectCountStat() {
        ImmutableMap<String, LocalDateTime> beginEndDay = getBeginEndDay(0);
        Long inspectCount = iotInspectOrderMapper.selectCount();
        IotInspectOrderPageReqVO iotInspectOrderPageReqVO = new IotInspectOrderPageReqVO();
        iotInspectOrderPageReqVO.setCreateTime(new LocalDateTime[]{beginEndDay.get("start"), beginEndDay.get("end")});
        Long inspectToday = iotInspectOrderMapper.selectCountByTimeAndStatus(iotInspectOrderPageReqVO);
        return success(ImmutableMap.of("total", inspectCount, "today", inspectToday));
    }

    @Resource
    private DictDataService dictDataService;
    @GetMapping("/home/device/status/{dept}")
    public CommonResult<List<Map<String, Object>>> getDeviceStatusStat(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        IotDevicePageReqVO iotDevicePageReqVO = new IotDevicePageReqVO();
        iotDevicePageReqVO.setDeptIds(new ArrayList<>(ids));
        List<IotDeviceDO> iotDeviceDOS = iotDeviceMapper.selectList(iotDevicePageReqVO);
        Map<String, Long> order = iotDeviceDOS.stream().collect(Collectors.groupingBy(IotDeviceDO::getDeviceStatus, Collectors.counting()));
        List<Map<String, Object>> results = new ArrayList<>();
        List<DictDataDO> pmsDeviceStatus = dictDataService.getDictDataListByDictType("pms_device_status");
        order.forEach((k,v)->{
            pmsDeviceStatus.stream().filter(e -> e.getValue().equals(k)).findFirst().ifPresent(e -> {
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("name", e.getLabel());
                resultMap.put("value", v);
                results.add(resultMap);
            });
        });
        return success(results);
    }

    @GetMapping("/home/device/type/{dept}")
    public CommonResult<List<Map<String, Object>>> getDeviceTypeStat(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        IotDevicePageReqVO iotDevicePageReqVO = new IotDevicePageReqVO();
        iotDevicePageReqVO.setDeptIds(new ArrayList<>(ids));
        List<IotDeviceDO> iotDeviceDOS = iotDeviceMapper.selectList(iotDevicePageReqVO);
        LinkedList<Map<String, Object>> results = new LinkedList<>();
        if ("rh".equals(dept)) {
            List<Map.Entry<Long, Long>> collect = iotDeviceDOS.stream().collect(Collectors.groupingBy(IotDeviceDO::getAssetClass, Collectors.counting())).entrySet().stream().sorted(Map.Entry.<Long, Long>comparingByValue().reversed()).collect(Collectors.toList());
            collect.forEach(e->{
                IotProductClassifyDO iotProductClassifyDO = iotProductClassifyMapper.selectById(e.getKey());
                if ("电驱增压机".equals(iotProductClassifyDO.getName())||"柴驱增压机".equals(iotProductClassifyDO.getName())||"液驱增压机".equals(iotProductClassifyDO.getName())||"电驱空压机".equals(iotProductClassifyDO.getName())||"柴驱空压机".equals(iotProductClassifyDO.getName())
                        ||"空气处理撬".equals(iotProductClassifyDO.getName())||"提纯撬".equals(iotProductClassifyDO.getName()) ||"膜组".equals(iotProductClassifyDO.getName())||"注水泵".equals(iotProductClassifyDO.getName())) {
                    Map<String, Object> map = new HashMap<>(4);
                    map.put("category", iotProductClassifyDO.getName());
                    map.put("value", e.getValue());
                    results.add(map);
                }
            });
        }else {
            List<Map.Entry<Long, Long>> collect = iotDeviceDOS.stream().collect(Collectors.groupingBy(IotDeviceDO::getAssetClass, Collectors.counting())).entrySet().stream().sorted(Map.Entry.<Long, Long>comparingByValue().reversed())
                    .limit(5)
                    .collect(Collectors.toList());
            collect.forEach(e ->{
                IotProductClassifyDO iotProductClassifyDO = iotProductClassifyMapper.selectById(e.getKey());
                Map<String, Object> map = new HashMap<>(4);
                map.put("category", iotProductClassifyDO.getName());
                map.put("value", e.getValue());
                results.add(map);
            });
        }

        return success(results);
    }

    @Data
    public static class ActiveDept {
        private String deptName;
        private Long active;
        private Long total;
    }

    @GetMapping("/home/dept")
    public CommonResult<List<Pms.deptStat>> getActiveDeptStat() {
        List<Pms.deptStat> userCountByDeptId = adminUserApi.getUserCountByDeptId(null);
        return success(userCountByDeptId);
    }

    @GetMapping("/home/safe")
    public CommonResult<String> getSafe() {
        List<IotSapStockDO> iotSapStockDOS = iotSapStockMapper.getSafeList();
        List<Long> ids = new ArrayList<>();
        iotSapStockDOS.forEach(e ->{
            if (e.getSafetyStock().compareTo(e.getQuantity())>0) {
                ids.add(e.getId());
            }
        });
        return success(String.valueOf(ids.size()));
    }

    @GetMapping("/inspect/device")
    public CommonResult<Map<String, Integer>> getDeviceStatus(IotCountDataDO vo) {
        Set<Long> ids = new HashSet<>();
        if (Objects.nonNull(vo.getDeptId())) {
            ids = deptService.getChildDeptIdListFromCache(vo.getDeptId());
            ids.add(vo.getDeptId());
        }
        List<IotInspectOrderDetailDO> detailDOList = iotInspectOrderDetailMapper.selectListStat(vo, ids);
        Map<Long, List<IotInspectOrderDetailDO>> collect = detailDOList.stream().collect(Collectors.groupingBy(IotInspectOrderDetailDO::getOrderId));
        AtomicInteger todo = new AtomicInteger();
        AtomicInteger finished = new AtomicInteger();
        AtomicInteger ignore = new AtomicInteger();
        collect.forEach( (k,v)->{
            Map<Long, List<IotInspectOrderDetailDO>> collect1 = v.stream().collect(Collectors.groupingBy(IotInspectOrderDetailDO::getDeviceId));
            collect1.forEach( (k1,v2)->{
                boolean b1 = v2.stream().allMatch(IotInspectOrderDetailDO::getIgnoreReason);
                if (b1) {
                    ignore.getAndIncrement();
                } else {
                    boolean b = v2.stream().anyMatch(f -> Objects.isNull(f.getIfNormal()));
                    if (b) {
                        todo.getAndIncrement();
                    }else {
                        finished.getAndIncrement();
                    }
                }
            });
        });
        return success(ImmutableMap.of("todo", todo.get(),"finished", finished.get(), "ignore", ignore.get()));
    }

    @GetMapping("/inspect/exception/device")
    public CommonResult<ImmutableMap<String, Long>> getDeviceException(IotCountDataDO vo) {
        Set<Long> ids;
        if (Objects.isNull(vo.getDeptId())){
            Long loginUserDeptId = SecurityFrameworkUtils.getLoginUserDeptId();
            String companyCode = deptUtil.getCompanyCode(loginUserDeptId);
            ids = deptUtil.getDeptIds(companyCode);
        } else {
            ids = deptService.getChildDeptIdListFromCache(vo.getDeptId());
            ids.add(vo.getDeptId());
        }
        Long deviceException = iotInspectOrderDetailMapper.selectDeviceException(vo, ids);
        return success(ImmutableMap.of("exceptionNum",deviceException));
    }

    @GetMapping("/rh/ywcb/{dept}")
    @PermitAll
    public CommonResult<Map<String, Object>> getRhYwcbStat(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        List<String> lastSevenDays = getLastSevenDays();
        String first = lastSevenDays.get(0);
        String last = lastSevenDays.get(lastSevenDays.size() - 1);
        LocalDateTime startOfDay = getStartOfDay(last);
        LocalDateTime endOfDay = getEndOfDay(first);
        LocalDateTime[] createTime = new LocalDateTime[]{startOfDay, endOfDay};
        //查询维修成本
        IotMaintainPageReqVO maintainPageReqVO = new IotMaintainPageReqVO();
        maintainPageReqVO.setDeptIds(ids);
        maintainPageReqVO.setExecuteDate(createTime);
        maintainPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<IotMaintainDO> repairOrders = iotMaintainService.getIotMaintainPage(maintainPageReqVO).getList();
        LinkedHashMap<String, Long> repairMap = countWxcbByDate(repairOrders, 7);

        // 查询保养成本
        IotMainWorkOrderPageReqVO workOrderReqVO = new IotMainWorkOrderPageReqVO();
        workOrderReqVO.setDeptIds(ids);
        workOrderReqVO.setCreateTime(createTime);
        List<IotMainWorkOrderDO> workOrders = iotMainWorkOrderService.workOrders(workOrderReqVO);
        LinkedHashMap<String, Long> byOutMap = countBycbByDate(workOrders, 7);
//        LinkedHashMap<String, Long> outMap = countYwcbByDate(outs, 7);
        LinkedList<Object> xAxis = new LinkedList<>();
        LinkedList<Object> outData = new LinkedList<>();
        repairMap.forEach( (k,v)->{
            xAxis.add(k);
            if (Objects.isNull(byOutMap.get(k))) {
                outData.add(v);
            } else {
                outData.add(v+byOutMap.get(k));
            }
        });

        return success(ImmutableMap.of("xAxis", xAxis, "series", outData));
    }

    @GetMapping("/rh/order/{dept}")
    @PermitAll
    public CommonResult<Map<String, Object>> getOrderNumberStat(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        List<String> lastSevenDays = getLastSevenDays();
        String first = lastSevenDays.get(0);
        String last = lastSevenDays.get(lastSevenDays.size() - 1);
        LocalDateTime startOfDay = getStartOfDay(last);
        LocalDateTime endOfDay = getEndOfDay(first);
        LocalDateTime[] createTime = new LocalDateTime[]{startOfDay, endOfDay};

        IotOpeationFillPageReqVO iotOpeationFillPageReqVO = new IotOpeationFillPageReqVO();
        iotOpeationFillPageReqVO.setCreateTime(createTime);
        iotOpeationFillPageReqVO.setDeptIds(new ArrayList<>(ids));
        List<Map<String, Object>> fills = iotOpeationFillMapper.selectListByCreateTime(iotOpeationFillPageReqVO).stream().map(e -> {
            Map<String, Object> abc = new HashMap<>();
            abc.put("id", e.getId());
            abc.put("createTime", e.getCreateTime());
            return abc;
        }).collect(Collectors.toList());
        LinkedHashMap<String, Long> fillMap = countRecordsByDate(fills, 7);
        LinkedList<Object> xAxis = new LinkedList<>();
        LinkedList<Object> fillData = new LinkedList<>();
        fillMap.forEach( (k,v)->{
            xAxis.add(k);
            fillData.add(v);
        });

        IotMaintainPageReqVO iotMaintainPageReqVO = new IotMaintainPageReqVO();
        iotMaintainPageReqVO.setCreateTime(createTime);
        List<Map<String, Object>> maintains = iotMaintainMapper.selectListByCreateTime(iotMaintainPageReqVO, ids).stream().map(e -> {
            Map<String, Object> abc = new HashMap<>();
            abc.put("id", e.getId());
            abc.put("createTime", e.getCreateTime());
            return abc;
        }).collect(Collectors.toList());
        Map<String, Long> maintainMap = countRecordsByDate(maintains, 7);
        LinkedList<Object> maintainData = new LinkedList<>();
        maintainMap.forEach( (k,v)->{
            maintainData.add(v);
        });

        IotMainWorkOrderPageReqVO iotMainWorkOrderPageReqVO = new IotMainWorkOrderPageReqVO();
        iotMainWorkOrderPageReqVO.setCreateTime(createTime);
        List<Map<String, Object>> works = iotMainWorkOrderMapper.selectListByCreateTime(iotMainWorkOrderPageReqVO,ids).stream().map(e -> {
            Map<String, Object> abc = new HashMap<>();
            abc.put("id", e.getId());
            abc.put("createTime", e.getCreateTime());
            return abc;
        }).collect(Collectors.toList());
        Map<String, Long> workMap = countRecordsByDate(works, 7);
        LinkedList<Object> workData = new LinkedList<>();
        workMap.forEach( (k,v)->{
            workData.add(v);
        });


        IotInspectOrderPageReqVO iotInspectOrderPageReqVO = new IotInspectOrderPageReqVO();
        iotInspectOrderPageReqVO.setCreateTime(createTime);
        List<Map<String, Object>> inspects = iotInspectOrderMapper.selectListByCreateTime(iotInspectOrderPageReqVO,ids).stream().map(e -> {
            Map<String, Object> abc = new HashMap<>();
            abc.put("id", e.getId());
            abc.put("createTime", e.getCreateTime());
            return abc;
        }).collect(Collectors.toList());
        Map<String, Long> inspectMap = countRecordsByDate(inspects, 7);
        LinkedList<Object> inspectData = new LinkedList<>();
        inspectMap.forEach( (k,v)->{
            inspectData.add(v);
        });

        ImmutableMap<String, Serializable> maintainResult = ImmutableMap.of("name", "维修工单~~en**repairOrder", "data", maintainData);
        ImmutableMap<String, Serializable> workResult = ImmutableMap.of("name", "保养工单~~en**maintenanceOrder", "data", workData);
        ImmutableMap<String, Serializable> inspectResult = ImmutableMap.of("name", "巡检工单~~en**inspectOrder", "data", inspectData);
        ImmutableMap<String, Serializable> fillResult = ImmutableMap.of("name", "运行记录~~en**operationRecord", "data", fillData);
        return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(maintainResult, workResult,inspectResult, fillResult)));
    }

    public static LinkedHashMap<String, Long> sumTotalByDate(List<Map<String, Object>> records, int days, String key) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate today = LocalDate.now();

        // 生成近days天的日期列表，初始值为0
        LinkedHashMap<String, Long> dateMap = new LinkedHashMap<>();
        for (int i = days - 1; i >= 0; i--) {
            LocalDate date = today.minusDays(i);
            dateMap.put(date.format(formatter), 0L);
        }

        // 统计每天的total字段之和
        Map<String, Long> sumMap = records.stream()
                .collect(Collectors.groupingBy(
                        record -> {
                            try {
                                // 提取日期部分（假设createTime格式为yyyy-MM-dd...）
                                return String.valueOf(record.get("createTime")).substring(0, 10);
                            } catch (Exception e) {
                                System.err.println("日期格式错误: " + record.get("createTime"));
                                return "invalid_date";
                            }
                        },
                        // 累加每天的total字段值，处理可能的格式问题
                        Collectors.summingLong(record -> {
                            try {
                                Object totalObj = record.get(key);
                                if (totalObj instanceof Number) {
                                    return ((Number) totalObj).longValue();
                                } else if (totalObj instanceof String) {
                                    String value = String.valueOf(totalObj).replace(".00","");
                                    return Long.parseLong(value);
                                } else {
//                                    System.err.println("total字段格式错误: " + totalObj);
                                    String value = String.valueOf(totalObj).replace(".00","");
                                    return Long.parseLong(value);
                                }
                            } catch (Exception e) {
                                System.err.println("处理total字段出错: " + e.getMessage());
                                return 0L;
                            }
                        })
                ));

        // 合并结果，确保所有日期都在返回结果中
        dateMap.forEach((date, sum) -> {
            if (sumMap.containsKey(date)) {
                dateMap.put(date, sumMap.get(date));
            }
        });

        return dateMap;
    }

    public static LinkedHashMap<String, Long> countYwcbByDate(List<IotOutboundDO> records, int days) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate today = LocalDate.now();

        // 生成近七天的日期列表
        LinkedHashMap<String, Long> dateMap = new LinkedHashMap<>();
        for (int i = days-1; i >= 0; i--) {
            LocalDate date = today.minusDays(i);
            dateMap.put(date.format(formatter), 0L);
        }

        Map<String, Long> amountMap = records.stream()
                .collect(Collectors.groupingBy(
                        record -> {
                            try {
                                // 提取日期部分（假设createTime是类似"yyyy-MM-ddHH:mm:ss"的字符串）
                                return String.valueOf(record.getCreateTime()).substring(0, 10);
                            } catch (Exception e) {
                                System.err.println("日期格式错误: " + record.getCreateTime());
                                return "invalid_date";
                            }
                        },
                        // 对每个分组计算金额总和：quantity * price累加
                        Collectors.summingLong(record -> record.getQuantity().multiply(record.getUnitPrice()).longValue())
                ));

        // 合并两个映射，确保所有日期都存在
        dateMap.forEach((date, count) -> {
            if (amountMap.containsKey(date)) {
                dateMap.put(date, amountMap.get(date));
            }
        });

        return dateMap;
    }

    public static LinkedHashMap<String, Long> countBycbByDate(List<IotMainWorkOrderDO> records, int days) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate today = LocalDate.now();

        // 生成近七天的日期列表
        LinkedHashMap<String, Long> dateMap = new LinkedHashMap<>();
        for (int i = days-1; i >= 0; i--) {
            LocalDate date = today.minusDays(i);
            dateMap.put(date.format(formatter), 0L);
        }

        Map<String, Long> amountMap = records.stream()
                .collect(Collectors.groupingBy(
                        record -> {
                            try {
                                // 提取日期部分（假设createTime是类似"yyyy-MM-ddHH:mm:ss"的字符串）
                                return String.valueOf(record.getCreateTime()).substring(0, 10);
                            } catch (Exception e) {
                                System.err.println("日期格式错误: " + record.getCreateTime());
                                return "invalid_date";
                            }
                        },
                        // 对每个分组计算金额总和：quantity * price累加
                        Collectors.summingLong(record -> record.getCost().longValue())
                ));

        // 合并两个映射，确保所有日期都存在
        dateMap.forEach((date, count) -> {
            if (amountMap.containsKey(date)) {
                dateMap.put(date, amountMap.get(date));
            }
        });

        return dateMap;
    }

    public static LinkedHashMap<String, Long> countWxcbByDate(List<IotMaintainDO> records, int days) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate today = LocalDate.now();

        // 生成近七天的日期列表
        LinkedHashMap<String, Long> dateMap = new LinkedHashMap<>();
        for (int i = days-1; i >= 0; i--) {
            LocalDate date = today.minusDays(i);
            dateMap.put(date.format(formatter), 0L);
        }

        Map<String, Long> amountMap = records.stream()
                .collect(Collectors.groupingBy(
                        record -> {
                            try {
                                // 提取日期部分（假设createTime是类似"yyyy-MM-ddHH:mm:ss"的字符串）
                                return String.valueOf(record.getCreateTime()).substring(0, 10);
                            } catch (Exception e) {
                                System.err.println("日期格式错误: " + record.getCreateTime());
                                return "invalid_date";
                            }
                        },
                        // 对每个分组计算金额总和：quantity * price累加
                        Collectors.summingLong(record -> Objects.isNull(record.getMaintainFee())?0L:record.getMaintainFee().longValue())
                ));

        // 合并两个映射，确保所有日期都存在
        dateMap.forEach((date, count) -> {
            if (amountMap.containsKey(date)) {
                dateMap.put(date, amountMap.get(date));
            }
        });

        return dateMap;
    }
    public static LinkedHashMap<String, Long> countRecordsByDate(List<Map<String, Object>> records, int days) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate today = LocalDate.now();

        // 生成近七天的日期列表
        LinkedHashMap<String, Long> dateMap = new LinkedHashMap<>();
        for (int i = days-1; i >= 0; i--) {
            LocalDate date = today.minusDays(i);
            dateMap.put(date.format(formatter), 0L);
        }

        // 统计每天的记录数量
        Map<String, Long> countMap = records.stream()
                .collect(Collectors.groupingBy(
                        record -> {
                            try {
                                // 提取日期部分
                                return String.valueOf(record.get("createTime")).substring(0, 10);
                            } catch (Exception e) {
                                System.err.println("日期格式错误: " + record.get("createTime"));
                                return "invalid_date";
                            }
                        },
                        Collectors.counting()
                ));

        // 合并两个映射，确保所有日期都存在
        dateMap.forEach((date, count) -> {
            if (countMap.containsKey(date)) {
                dateMap.put(date, countMap.get(date));
            }
        });

        return dateMap;
    }

    @GetMapping("/rh/zql/{dept}")
    @PermitAll
    public CommonResult<Map<String, Object>> rhOrder(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        List<String> lastSevenDays = getLastSevenDays();
        String first = lastSevenDays.get(0);
        String last = lastSevenDays.get(lastSevenDays.size() - 1);
        LocalDateTime startOfDay = getStartOfDay(last);
        LocalDateTime endOfDay = getEndOfDay(first);
        LocalDateTime[] createTime = new LocalDateTime[]{startOfDay, endOfDay};

        IotDeviceRunLogPageReqVO iotDeviceRunLogPageReqVO = new IotDeviceRunLogPageReqVO();
        iotDeviceRunLogPageReqVO.setCreateTime(createTime);
        iotDeviceRunLogPageReqVO.setDeptIds(new ArrayList<>(ids));
        iotDeviceRunLogPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        iotDeviceRunLogPageReqVO.setPointName("累计注气量");
        List<IotDeviceRunLogRespVO> iotDeviceRunLogRespVOS = iotDeviceRunLogMapper.selectListByCreateTimeAndDeptList(iotDeviceRunLogPageReqVO);
        List<Map<String, Object>> fills = iotDeviceRunLogRespVOS
                .stream().map(e -> {
            Map<String, Object> abc = new HashMap<>();
            abc.put("id", e.getId());
            abc.put("createTime", e.getCreateTime());
            abc.put("total", e.getTotalRunTime());
            abc.put("today", e.getFillContent());
            return abc;
        }).collect(Collectors.toList());
        LinkedHashMap<String, Long> fillMap = sumTotalByDate(fills, 7,"total");
        LinkedList<Object> xAxis = new LinkedList<>();
        LinkedList<Object> fillData = new LinkedList<>();
        fillMap.forEach( (k,v)->{
            xAxis.add(k);
            fillData.add(v);
        });

        iotDeviceRunLogPageReqVO.setPointName("累计注水量");
        List<IotDeviceRunLogRespVO> waterDOs = iotDeviceRunLogMapper.selectListByCreateTimeAndDeptList(iotDeviceRunLogPageReqVO);
        List<Map<String, Object>> waters = waterDOs
                .stream().map(e -> {
                    Map<String, Object> abc = new HashMap<>();
                    abc.put("id", e.getId());
                    abc.put("createTime", e.getCreateTime());
                    abc.put("total", e.getTotalRunTime());
                    abc.put("today", e.getFillContent());
                    return abc;
                }).collect(Collectors.toList());
        LinkedHashMap<String, Long> waterMap = sumTotalByDate(waters, 7,"total");
        LinkedList<Object> waterXAxis = new LinkedList<>();
        LinkedList<Object> waterData = new LinkedList<>();
        waterMap.forEach( (k,v)->{
            waterXAxis.add(k);
            waterData.add(v);
        });

        ImmutableMap<String, Serializable> fillResult = ImmutableMap.of("name", "累计注气量~~en**cumulative gas injection", "data", fillData);
        ImmutableMap<String, Serializable> waterResult = ImmutableMap.of("name", "累计注水量~~en**cumulative water injection", "data", waterData);
        return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(fillResult,waterResult)));

    }
    @GetMapping("/rh/zql/today/{dept}")
    @PermitAll
    public CommonResult<Map<String, Object>> rhOrderToday(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        List<String> lastSevenDays = getLastSevenDays();
        String first = lastSevenDays.get(0);
        String last = lastSevenDays.get(lastSevenDays.size() - 1);
        LocalDateTime startOfDay = getStartOfDay(last);
        LocalDateTime endOfDay = getEndOfDay(first);
        LocalDateTime[] createTime = new LocalDateTime[]{startOfDay, endOfDay};

        IotDeviceRunLogPageReqVO iotDeviceRunLogPageReqVO = new IotDeviceRunLogPageReqVO();
        iotDeviceRunLogPageReqVO.setCreateTime(createTime);
        iotDeviceRunLogPageReqVO.setDeptIds(new ArrayList<>(ids));
        iotDeviceRunLogPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        iotDeviceRunLogPageReqVO.setPointName("当日注气量");
        List<Map<String, Object>> fills = iotDeviceRunLogMapper.selectListByCreateTimeAndDeptList(iotDeviceRunLogPageReqVO).stream().map(e -> {
            Map<String, Object> abc = new HashMap<>();
            abc.put("id", e.getId());
            abc.put("createTime", e.getCreateTime());
            abc.put("total", e.getTotalRunTime());
            abc.put("today", e.getFillContent());
            return abc;
        }).collect(Collectors.toList());
        LinkedHashMap<String, Long> fillMap = sumTotalByDate(fills, 7,"today");
        LinkedList<Object> xAxis = new LinkedList<>();
        LinkedList<Object> fillData = new LinkedList<>();
        fillMap.forEach( (k,v)->{
            xAxis.add(k);
            fillData.add(v);
        });

//        iotDeviceRunLogPageReqVO.setPointName("当日注水量");
//        List<Map<String, Object>> waters = iotDeviceRunLogMapper.selectListByCreateTimeAndDeptList(iotDeviceRunLogPageReqVO).stream().map(e -> {
//            Map<String, Object> abc = new HashMap<>();
//            abc.put("id", e.getId());
//            abc.put("createTime", e.getCreateTime());
//            abc.put("total", e.getTotalRunTime());
//            abc.put("today", e.getFillContent());
//            return abc;
//        }).collect(Collectors.toList());
//        LinkedHashMap<String, Long> waterMap = sumTotalByDate(waters, 7,"today");
//        LinkedList<Object> waterxAxis = new LinkedList<>();
//        LinkedList<Object> waterData = new LinkedList<>();
//        waterMap.forEach( (k,v)->{
//            waterxAxis.add(k);
//            waterData.add(v);
//        });

        ImmutableMap<String, Serializable> fillResult = ImmutableMap.of("name", "当日注气量~~en**daily gas injection", "data", fillData);
//        ImmutableMap<String, Serializable> waterResult = ImmutableMap.of("name", "当日注水量~~en**daily water injection", "data", waterData);
        return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(fillResult)));

    }


    @GetMapping("/rh/zql/daily/{dept}")
    @PermitAll
    public CommonResult<Map<String, Object>> rhOrderDaily(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        List<String> lastSevenDays = getLastSevenDays();
        String first = lastSevenDays.get(0);
        String last = lastSevenDays.get(lastSevenDays.size() - 1);
        LocalDateTime startOfDay = getStartOfDay(last);
        LocalDateTime endOfDay = getEndOfDay(first);
        LocalDateTime[] createTime = new LocalDateTime[]{startOfDay, endOfDay};

        IotRhDailyReportPageReqVO iotRhDailyReportPageReqVO = new IotRhDailyReportPageReqVO();
        iotRhDailyReportPageReqVO.setCreateTime(createTime);
        iotRhDailyReportPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<Map<String, Object>> fills = iotRhDailyReportMapper.selectPage(iotRhDailyReportPageReqVO).getList().stream().map(e -> {
            Map<String, Object> abc = new HashMap<>();
            abc.put("id", e.getId());
            abc.put("createTime", e.getCreateTime());
            abc.put("today", e.getDailyGasInjection());
            return abc;
        }).collect(Collectors.toList());
        LinkedHashMap<String, Long> fillMap = sumTotalByDate(fills, 7,"today");
        LinkedList<Object> xAxis = new LinkedList<>();
        LinkedList<Object> fillData = new LinkedList<>();
        fillMap.forEach( (k,v)->{
            xAxis.add(k);
            fillData.add(v);
        });

//        iotDeviceRunLogPageReqVO.setPointName("当日注水量");
//        List<Map<String, Object>> waters = iotDeviceRunLogMapper.selectListByCreateTimeAndDeptList(iotDeviceRunLogPageReqVO).stream().map(e -> {
//            Map<String, Object> abc = new HashMap<>();
//            abc.put("id", e.getId());
//            abc.put("createTime", e.getCreateTime());
//            abc.put("total", e.getTotalRunTime());
//            abc.put("today", e.getFillContent());
//            return abc;
//        }).collect(Collectors.toList());
//        LinkedHashMap<String, Long> waterMap = sumTotalByDate(waters, 7,"today");
//        LinkedList<Object> waterxAxis = new LinkedList<>();
//        LinkedList<Object> waterData = new LinkedList<>();
//        waterMap.forEach( (k,v)->{
//            waterxAxis.add(k);
//            waterData.add(v);
//        });

        ImmutableMap<String, Serializable> fillResult = ImmutableMap.of("name", "当日注气量~~en**daily gas injection", "data", fillData);
//        ImmutableMap<String, Serializable> waterResult = ImmutableMap.of("name", "当日注水量~~en**daily water injection", "data", waterData);
        return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(fillResult)));

    }

    @Operation(summary = "瑞恒当日注气量 累计注气量")
    @GetMapping("/rh/zql")
    @PermitAll
    public CommonResult<BigDecimal> dailyZql(IotRhDailyReportPageReqVO reqVO) {
        BigDecimal result = BigDecimal.ZERO;
        if (ObjUtil.isEmpty(reqVO)) {
            return success(result);
        }
        reqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        PageResult<IotRhDailyReportDO> pageReports = iotRhDailyReportMapper.selectPage(reqVO);
        if (ObjUtil.isEmpty(pageReports)) {
            return success(result);
        }
        List<IotRhDailyReportDO> reports = pageReports.getList();
        if (CollUtil.isEmpty(reports)) {
            return success(result);
        }
        for (IotRhDailyReportDO report : reports) {
            BigDecimal tempGasInjection = report.getDailyGasInjection();
            result = result.add(tempGasInjection);
        }
        // 注气量单位设置成 万方
        BigDecimal convertedGasInjection = result.divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);
        return success(convertedGasInjection);
    }

    @PermitAll
    @GetMapping("/project/{dept}")
    public CommonResult<List<ImmutableMap<String, ? extends Serializable>>> projectStat(@PathVariable("dept") String dept) {
        List<DeptRespDTO> deptByName = deptApi.getDeptByName("瑞鹰国际");
        if (CollUtil.isEmpty(deptByName)) {
            throw new ServiceException(new ErrorCode(122, "没有部门"));
        }
        List<DeptRespDTO> childDeptList = deptApi.getChildDeptList(deptByName.get(0).getId());
        List<DeptRespDTO> projects = childDeptList.stream().filter(e -> deptByName.get(0).getId().equals(e.getParentId())).collect(Collectors.toList());
        List<ImmutableMap<String, ? extends Serializable>> result = projects.stream().map(e -> {
            List<DeptRespDTO> allSubclasses = findAllSubclasses(childDeptList, e.getId());
            Set<Long> collect = allSubclasses.stream().map(DeptRespDTO::getId).collect(Collectors.toSet());
            collect.add(e.getId());
            Long l = iotDeviceMapper.selectByDept(collect);
            return ImmutableMap.of("name", e.getName(), "value", l);
        }).collect(Collectors.toList());
        return success(result);
    }


    private List<DeptRespDTO> findAllSubclasses(List<DeptRespDTO> allNodes, Long parentId) {
        List<DeptRespDTO> result = new ArrayList<>();

        // 先找到直接子节点
        for (DeptRespDTO node : allNodes) {
            if (parentId.equals(node.getParentId())) {
                result.add(node);
                // 递归查找子节点的子节点，并添加到结果中
                result.addAll(findAllSubclasses(allNodes, node.getId()));
            }
        }
        return result;
    }

    @PermitAll
    @GetMapping("/mttr")
    public CommonResult<String> getMttr() {
        List<IotFailureReportDO> failureReportDOS = iotFailureReportMapper.selectList();
        List<IotFailureReportDO> collect = failureReportDOS.stream().filter(e -> Objects.nonNull(e.getDealHour())&&(e.getDealHour().compareTo(BigDecimal.ZERO) > 0)).collect(Collectors.toList());
        if (CollUtil.isEmpty(collect)) {
            return success("0");
        } else {
            int size = collect.size();
            double sum = collect.stream().mapToDouble(re -> re.getDealHour().doubleValue()).sum();
            Double result = sum/size;
            DecimalFormat df = new DecimalFormat("#.0");
            String formattedResult = df.format(result);
            return success(formattedResult);
        }
    }


    @PermitAll
    @GetMapping("/year/total/gas/{dept}")
    public CommonResult<ImmutableMap> getYearTotalGas(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        //获取近一年的月份
        List<String> lastYearMonthRanges = getLastYearMonthRanges().stream().map(MonthRange::getYearMonth).collect(Collectors.toList());
        IotDeviceRunLogPageReqVO iotDeviceRunLogPageReqVO = new IotDeviceRunLogPageReqVO();
        iotDeviceRunLogPageReqVO.setDeptIds(new ArrayList<>(ids));
        iotDeviceRunLogPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        iotDeviceRunLogPageReqVO.setPointName("当日注气量");
        List<YearTotalGas> yearTotalGases = iotDeviceRunLogMapper.selectYearTotalGas(iotDeviceRunLogPageReqVO);
        LinkedList<String> result = new LinkedList<>();
        lastYearMonthRanges.forEach(lastYearMonthRange -> {
            YearTotalGas yearTotalGas = yearTotalGases.stream().filter(e -> e.getMonth().equals(lastYearMonthRange)).findAny().orElse(null);
            if (Objects.isNull(yearTotalGas)) {
                result.add("0");
            } else {
                result.add(NumberUtils.formatNumber(yearTotalGas.getTotalGas()));
            }
        });
        ImmutableMap<String, Serializable> fillResult = ImmutableMap.of("name", "累计注气量~~en**cumulative gas injection", "data", result);
        return success(ImmutableMap.of("xAxis", lastYearMonthRanges, "series", ImmutableList.of(fillResult)));

    }

    @PermitAll
    @GetMapping("/year/total/gases/{dept}")
    public CommonResult<ImmutableMap> getYearTotalGases(@PathVariable("dept") String dept) {
        Set<Long> ids = getDeptIds(dept);
        //获取近一年的月份
        List<String> lastYearMonthRanges = getLastYearMonthRanges().stream().map(MonthRange::getYearMonth).collect(Collectors.toList());
        IotRhDailyReportPageReqVO iotRhDailyReportPageReqVO = new IotRhDailyReportPageReqVO();
//        iotRhDailyReportPageReqVO.setDeptIds(new ArrayList<>(ids));
        iotRhDailyReportPageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<YearTotalGas> yearTotalGases = iotRhDailyReportMapper.selectYearTotalGas(iotRhDailyReportPageReqVO);
        LinkedList<String> result = new LinkedList<>();
        lastYearMonthRanges.forEach(lastYearMonthRange -> {
            YearTotalGas yearTotalGas = yearTotalGases.stream().filter(e -> e.getMonth().equals(lastYearMonthRange)).findAny().orElse(null);
            if (Objects.isNull(yearTotalGas)) {
                result.add("0");
            } else {
                result.add(NumberUtils.formatNumber(yearTotalGas.getTotalGas()));
            }
        });
        ImmutableMap<String, Serializable> fillResult = ImmutableMap.of("name", "累计注气量~~en**cumulative gas injection", "data", result);
        return success(ImmutableMap.of("xAxis", lastYearMonthRanges, "series", ImmutableList.of(fillResult)));

    }

    @GetMapping("/number")
    @Operation(summary = "获取巡检计划数量")
    @PermitAll
    public CommonResult<ImmutableMap> getPlanDeviceNumber() {
        Set<Long> rhids = getDeptIds("rh");
        Set<Long> rdids = getDeptIds("rd");
        Set<Long> ryids = getDeptIds("ry");
        IotInspectPlanPageReqVO rh = new IotInspectPlanPageReqVO();
        rh.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<IotInspectPlanDO> rhplans = iotInspectPlanMapper.selectPage(rh, rhids).getList().stream().filter(e -> !e.getDeleted()).collect(Collectors.toList());
        List<IotInspectPlanDO> rdplans = iotInspectPlanMapper.selectPage(rh, rdids).getList().stream().filter(e -> !e.getDeleted()).collect(Collectors.toList());
        List<IotInspectPlanDO> ryplans = iotInspectPlanMapper.selectPage(rh, ryids).getList().stream().filter(e -> !e.getDeleted()).collect(Collectors.toList());

        AtomicInteger rhcount = new AtomicInteger();
        rhplans.forEach(e ->{
            JSONArray objects = JSON.parseArray(e.getDeviceIds());
            int size = objects.size();
            rhcount.set(rhcount.get() + size);
        });

        AtomicInteger rdcount = new AtomicInteger();
        rdplans.forEach(e ->{
            JSONArray objects = JSON.parseArray(e.getDeviceIds());
            int size = objects.size();
            rdcount.set(rdcount.get() + size);
        });

        AtomicInteger rycount = new AtomicInteger();
        ryplans.forEach(e ->{
            JSONArray objects = JSON.parseArray(e.getDeviceIds());
            int size = objects.size();
            rycount.set(rycount.get() + size);
        });

        return success(ImmutableMap.of("瑞恒", rhcount.get(),"瑞都",rdcount.get(),"瑞鹰",rycount.get()));
    }

    /**
     * 统计 瑞鹰 158 的 钻井 修井工作量
     * @param type drill钻井  repair修井
     * @return
     */
    @GetMapping("/ry/dailyReport/{type}")
    @PermitAll
    public CommonResult<Map<String, Object>> getRyDailyReportStat(@PathVariable("type") String type) {
        if (StrUtil.isBlank(type)) {
            return success(new HashMap<>());
        }
        // 查询瑞鹰所有 队伍 项目部
        Set<Long> rdChildDeptIds = deptService.getChildDeptIdListFromCache(158l);
        List<DeptDO> depts =deptService.getDeptList(rdChildDeptIds);
        // key队伍id      value队伍所属项目部id      包含队伍的项目部
        Map<Long, Long> teamProjectPair = new HashMap<>();
        // 项目部id集合
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id     value项目部名称
        Map<Long, String> projectDeptPair = new HashMap<>();

        IotDeptTypePageReqVO deptTypeReqVO = new IotDeptTypePageReqVO();
        // 查询 钻井 修井 类型的部门
        if ("repair".equals(type)) {
            // 修井
            deptTypeReqVO.setType("xj");
        } else {
            // 钻井
            deptTypeReqVO.setType("zj");
        }
        // 找到钻井队伍对应的项目部 修井队伍对应的项目部
        Set<Long> zjDeptIds = new HashSet<>();
        Set<Long> xjDeptIds = new HashSet<>();
        Set<String> xjDeptNames = new HashSet<>();
        Set<String> zjDeptNames = new HashSet<>();
        List<IotDeptTypeDO> deptTypes = iotDeptTypeMapper.selectList(deptTypeReqVO);
        List<Long> zjOrXjDeptIds = new ArrayList<>();
        if (CollUtil.isNotEmpty(deptTypes)) {
            deptTypes.forEach(dept -> {
                zjOrXjDeptIds.add(dept.getDeptId());
                if ("zj".equals(dept.getType())) {
                    zjDeptIds.add(dept.getDeptId());
                }
                if ("xj".equals(dept.getType())) {
                    xjDeptIds.add(dept.getDeptId());
                }
            });
        }

        if (CollUtil.isNotEmpty(depts)) {
            depts.forEach(dept -> {
                // 类型(公司级1 项目部2 队伍3)
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(dept.getId());
                    projectDeptPair.put(dept.getId(), dept.getName());
                }
                if ("3".equals(dept.getType()) && zjOrXjDeptIds.contains(dept.getId())) {
                    teamProjectPair.put(dept.getId(), dept.getParentId());
                }
            });
            // 筛选出所有钻井项目部
            teamProjectPair.forEach((teamDeptId, projectDeptId) -> {
                if (zjDeptIds.contains(teamDeptId)) {
                    // 钻井部门
                    if (projectDeptPair.containsKey(projectDeptId)) {
                        zjDeptNames.add(projectDeptPair.get(projectDeptId));
                    }
                }
                if (xjDeptIds.contains(teamDeptId)) {
                    // 修井部门
                    if (projectDeptPair.containsKey(projectDeptId)) {
                        xjDeptNames.add(projectDeptPair.get(projectDeptId));
                    }
                }
            });
            // 筛选出所有修井项目部
        }
        IotRyDailyReportPageReqVO reqVO = new IotRyDailyReportPageReqVO();
        List<IotRyDailyReportTaskCountVO> repairTaskCounts = new ArrayList<>();
        if ("repair".equals(type)) {
            // 修井
            reqVO.setProjectClassification("2");
            // 修井日报统计 月完井数 年完井数
            List<IotRyDailyReportTaskCountVO> repairReports = iotRyDailyReportService.countDateRepairTasksByDept();
            Map<String, Integer> projectDeptMonthCountPair = new HashMap<>();
            Map<String, Integer> projectDeptYearCountPair = new HashMap<>();
            // 遍历 集合 repairReports 找到队伍对应的项目部
            if (CollUtil.isNotEmpty(repairReports)) {
                repairReports.forEach(report -> {
                    if (teamProjectPair.containsKey(report.getDeptId())) {
                        Long projectDeptId = teamProjectPair.get(report.getDeptId());
                        if (projectDeptPair.containsKey(projectDeptId)) {
                            // 项目部id 对应的项目部名称
                            String projectDeptName = projectDeptPair.get(projectDeptId);
                            // 设置月完井数
                            if (projectDeptMonthCountPair.containsKey(projectDeptName)) {
                                Integer tempCount = projectDeptMonthCountPair.get(projectDeptName);
                                Integer monthCompletedTaskCount = report.getMonthCompletedTaskCount();
                                projectDeptMonthCountPair.put(projectDeptName, tempCount+monthCompletedTaskCount);
                            } else {
                                Integer monthCompletedTaskCount = report.getMonthCompletedTaskCount();
                                projectDeptMonthCountPair.put(projectDeptName, monthCompletedTaskCount);
                            }
                            // 设置年完井数
                            if (projectDeptYearCountPair.containsKey(projectDeptName)) {
                                Integer tempCount = projectDeptYearCountPair.get(projectDeptName);
                                Integer yearCompletedTaskCount = report.getYearCompletedTaskCount();
                                projectDeptYearCountPair.put(projectDeptName, tempCount+yearCompletedTaskCount);
                            } else {
                                Integer yearCompletedTaskCount = report.getYearCompletedTaskCount();
                                projectDeptYearCountPair.put(projectDeptName, yearCompletedTaskCount);
                            }
                        }
                    }
                });
            }
            // 遍历所有项目部 没有产生运行数据的项目部 赋值 0
            // 钻井 时 只显示 钻井相关的项目部
            // 查询修井数据时，只显示修井相关的项目部
            projectDeptPair.forEach((projectDeptId, projectDeptName) -> {
                if (!projectDeptMonthCountPair.containsKey(projectDeptName)) {
                    projectDeptMonthCountPair.put(projectDeptName, 0);
                }
                if (!projectDeptYearCountPair.containsKey(projectDeptName)) {
                    projectDeptYearCountPair.put(projectDeptName, 0);
                }
            });

            LinkedList<Object> xAxis = new LinkedList<>();
            LinkedList<Object> monthData = new LinkedList<>();
            LinkedList<Object> yearData = new LinkedList<>();

            projectDeptMonthCountPair.forEach( (k,v)->{
                if (xjDeptNames.contains(k)) {
                    xAxis.add(k);
                    monthData.add(v);
                    if (projectDeptYearCountPair.containsKey(k)) {
                        Integer yearCount = projectDeptYearCountPair.get(k);
                        yearData.add(yearCount);
                    }
                }
            });
            ImmutableMap<String, Serializable> monthResult = ImmutableMap.of("name", "月完井数~~en**monthWell", "data", monthData);
            ImmutableMap<String, Serializable> yearResult = ImmutableMap.of("name", "年完井数~~en**YearWell", "data", yearData);
            return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(monthResult, yearResult)));
        } else {
            // 钻井
            reqVO.setProjectClassification("1");
            // 查询钻井的日报统计 日进尺 月累计进尺 年累计进尺
            List<IotRyDailyReportTaskCountVO> repairReports = iotRyDailyReportService.countDateDrillTasksByDept();
            Map<String, BigDecimal> projectDeptDailyFootagePair = new HashMap<>();
            Map<String, BigDecimal> projectDeptMonthFootagePair = new HashMap<>();
            Map<String, BigDecimal> projectDeptYearFootagePair = new HashMap<>();
            if (CollUtil.isNotEmpty(repairReports)) {
                repairReports.forEach(report -> {
                    if (teamProjectPair.containsKey(report.getDeptId())) {
                        Long projectDeptId = teamProjectPair.get(report.getDeptId());
                        if (projectDeptPair.containsKey(projectDeptId)) {
                            // 项目部id 对应的项目部名称
                            String projectDeptName = projectDeptPair.get(projectDeptId);
                            // 设置日进尺
                            if (projectDeptDailyFootagePair.containsKey(projectDeptName)) {
                                BigDecimal tempFootage = projectDeptDailyFootagePair.get(projectDeptName);
                                BigDecimal existFootage = report.getDailyFootage();
                                projectDeptDailyFootagePair.put(projectDeptName, tempFootage.add(existFootage));
                            } else {
                                BigDecimal tempFootage = report.getDailyFootage();
                                projectDeptDailyFootagePair.put(projectDeptName, tempFootage);
                            }
                            // 设置月累计进尺
                            if (projectDeptMonthFootagePair.containsKey(projectDeptName)) {
                                BigDecimal tempFootage = projectDeptMonthFootagePair.get(projectDeptName);
                                BigDecimal existFootage = report.getMonthlyFootage();
                                projectDeptMonthFootagePair.put(projectDeptName, tempFootage.add(existFootage));
                            } else {
                                BigDecimal tempFootage = report.getMonthlyFootage();
                                projectDeptMonthFootagePair.put(projectDeptName, tempFootage);
                            }
                            // 设置年累计进尺
                            if (projectDeptYearFootagePair.containsKey(projectDeptName)) {
                                BigDecimal tempFootage = projectDeptYearFootagePair.get(projectDeptName);
                                BigDecimal existFootage = report.getAnnualFootage();
                                projectDeptYearFootagePair.put(projectDeptName, tempFootage.add(existFootage));
                            } else {
                                BigDecimal tempFootage = report.getAnnualFootage();
                                projectDeptYearFootagePair.put(projectDeptName, tempFootage);
                            }
                        }
                    }
                });
            }
            // 遍历所有项目部 没有产生运行数据的项目部 进尺 赋值 0
            projectDeptPair.forEach((projectDeptId, projectDeptName) -> {
                if (!projectDeptDailyFootagePair.containsKey(projectDeptName)) {
                    projectDeptDailyFootagePair.put(projectDeptName, BigDecimal.ZERO);
                }
                if (!projectDeptMonthFootagePair.containsKey(projectDeptName)) {
                    projectDeptMonthFootagePair.put(projectDeptName, BigDecimal.ZERO);
                }
                if (!projectDeptYearFootagePair.containsKey(projectDeptName)) {
                    projectDeptYearFootagePair.put(projectDeptName, BigDecimal.ZERO);
                }
            });

            LinkedList<Object> xAxis = new LinkedList<>();
            LinkedList<Object> dailyData = new LinkedList<>();
            LinkedList<Object> monthData = new LinkedList<>();
            LinkedList<Object> yearData = new LinkedList<>();

            projectDeptDailyFootagePair.forEach( (k,v)->{
                if (zjDeptNames.contains(k)) {
                    xAxis.add(k);
                    dailyData.add(v);
                    if (projectDeptMonthFootagePair.containsKey(k)) {
                        BigDecimal monthlyFootage = projectDeptMonthFootagePair.get(k);
                        monthData.add(monthlyFootage);
                    }
                    if (projectDeptYearFootagePair.containsKey(k)) {
                        BigDecimal annualFootage = projectDeptYearFootagePair.get(k);
                        yearData.add(annualFootage);
                    }
                }
            });

            ImmutableMap<String, Serializable> dailyResult = ImmutableMap.of("name", "日进尺~~en**dailyFootage", "data", dailyData);
            ImmutableMap<String, Serializable> monthResult = ImmutableMap.of("name", "月累进尺~~en**monthlyFootage", "data", monthData);
            ImmutableMap<String, Serializable> yearResult = ImmutableMap.of("name", "年累进尺~~en**annualFootage", "data", yearData);
            return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(dailyResult, monthResult, yearResult)));
        }
    }

    /**
     * 按队伍 统计 瑞鹰 158 的 钻井 完井情况
     * @return
     */
    @GetMapping("/ry/dailyReport/rigFinished")
    @PermitAll
    public CommonResult<Map<String, Object>> getRyDailyReportRigFinished() {
        // 查询瑞鹰所有 队伍 项目部
        Set<Long> rdChildDeptIds = deptService.getChildDeptIdListFromCache(158l);
        List<DeptDO> depts =deptService.getDeptList(rdChildDeptIds);
        // key队伍id      value队伍所属项目部id      包含队伍的项目部
        Map<Long, Long> teamProjectPair = new HashMap<>();
        // key队伍id      value队伍名称
        Map<Long, String> teamPair = new HashMap<>();
        // 项目部id集合
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id     value项目部名称
        Map<Long, String> projectDeptPair = new HashMap<>();

        // 查询 钻井 业务相关 部门
        IotDeptTypePageReqVO deptTypeReqVO = new IotDeptTypePageReqVO();
        deptTypeReqVO.setType("zj");
        List<IotDeptTypeDO> deptTypes = iotDeptTypeMapper.selectList(deptTypeReqVO);
        List<Long> zjOrXjDeptIds = new ArrayList<>();
        if (CollUtil.isNotEmpty(deptTypes)) {
            deptTypes.forEach(dept -> {
                zjOrXjDeptIds.add(dept.getDeptId());
            });
        }

        if (CollUtil.isNotEmpty(depts)) {
            depts.forEach(dept -> {
                // 类型(公司级1 项目部2 队伍3)
                if ("2".equals(dept.getType())) {
                    // 项目部
                    projectDeptIds.add(dept.getId());
                    projectDeptPair.put(dept.getId(), dept.getName());
                }
                if ("3".equals(dept.getType()) && zjOrXjDeptIds.contains(dept.getId())) {
                    // 队伍
                    teamProjectPair.put(dept.getId(), dept.getParentId());
                    teamPair.put(dept.getId(), dept.getName());
                }
            });
        }

        IotRyDailyReportPageReqVO reqVO = new IotRyDailyReportPageReqVO();
        // 钻井
        reqVO.setProjectClassification("1");
        // 钻井 日报统计 月完井数 年完井数
        List<IotRyDailyReportTaskCountVO> repairReports = iotRyDailyReportService.countDateRigTasksByDepartment();
        Map<String, Integer> deptDailyPair = new HashMap<>();
        Map<String, Integer> deptMonthlyPair = new HashMap<>();
        Map<String, Integer> deptAnnualPair = new HashMap<>();
        // 遍历集合 repairReports 找到对应的队伍
        if (CollUtil.isNotEmpty(repairReports)) {
            repairReports.forEach(report -> {
                if (teamPair.containsKey(report.getDeptId())) {
                    String deptName = teamPair.get(report.getDeptId());
                    // 设置日完井数
                    deptDailyPair.put(deptName, report.getCompletedTaskCount());
                    // 设置月完井数
                    deptMonthlyPair.put(deptName, report.getMonthCompletedTaskCount());
                    deptAnnualPair.put(deptName, report.getYearCompletedTaskCount());
                }
            });
        }
        // 遍历所有队伍 没有产生运行数据的队伍 赋值 0
        teamPair.forEach((deptId, deptName) -> {
            if (!deptDailyPair.containsKey(deptName)) {
                deptDailyPair.put(deptName, 0);
            }
            if (!deptMonthlyPair.containsKey(deptName)) {
                deptMonthlyPair.put(deptName, 0);
            }
            if (!deptAnnualPair.containsKey(deptName)) {
                deptAnnualPair.put(deptName, 0);
            }
        });

        LinkedList<Object> xAxis = new LinkedList<>();
        LinkedList<Object> dailyData = new LinkedList<>();
        LinkedList<Object> monthData = new LinkedList<>();
        LinkedList<Object> yearData = new LinkedList<>();

        deptDailyPair.forEach( (k,v)->{
            xAxis.add(k);
            dailyData.add(v);
            if (deptMonthlyPair.containsKey(k)) {
                Integer monthCount = deptMonthlyPair.get(k);
                monthData.add(monthCount);
            }
            if (deptAnnualPair.containsKey(k)) {
                Integer yearCount = deptAnnualPair.get(k);
                yearData.add(yearCount);
            }
        });
//        ImmutableMap<String, Serializable> dailyResult = ImmutableMap.of("name", "日累完成井数~~en**dailyFinished", "data", dailyData);
        ImmutableMap<String, Serializable> monthResult = ImmutableMap.of("name", "月累完成井数~~en**monthlyFinished", "data", monthData);
        ImmutableMap<String, Serializable> yearResult = ImmutableMap.of("name", "年累完井数~~en**annualFinished", "data", yearData);
        return success(ImmutableMap.of("xAxis", xAxis, "series", ImmutableList.of(monthResult, yearResult)));
    }

    /**
     * 瑞恒 设备利用率 按项目部统计
     * @return
     */
    @GetMapping("/rh/device/utilizationRate")
    @PermitAll
    public CommonResult<List<ProjectUtilizationRateVo>> utilizationRate(IotRhDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        List<Long> sortedProjectIds = new ArrayList<>();
        sortedProjectIds.add(164l); // 塔河项目部
        sortedProjectIds.add(165l); // 塔里木项目部
        sortedProjectIds.add(160l); // 吐哈项目部
        sortedProjectIds.add(256l); // 川庆项目部
        sortedProjectIds.add(269l); // 非洲项目部
        sortedProjectIds.add(273l); // 南美项目部
        sortedProjectIds.add(275l); // 中东项目部
        sortedProjectIds.add(282l); // 中亚项目部
        // 各项目部的设备利用率集合
        List<ProjectUtilizationRateVo> rates = new ArrayList<>();
        // 查询瑞恒 157l 所有项目部
        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(157l);
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // 队伍id 集合
        Set<Long> teamDepartmentIds = new HashSet<>();

        // 筛选瑞恒 主设备 rq_iot_rh_main_device_category
        Set<Long> mainDeviceCategoryIds = new HashSet<>();
        List<DictDataDO> constructionStatusDictData = dictDataService.getDictDataListByDictType("rq_iot_rh_main_device_category");
        if (CollUtil.isNotEmpty(constructionStatusDictData)) {
            constructionStatusDictData.forEach(data -> {
                String value = data.getValue();
                if (NumberUtil.isNumber(value)) {
                    Long longValue = Long.valueOf(value);
                    mainDeviceCategoryIds.add(longValue);
                }
            });
        }

        // 查询 瑞恒 所有设备 只统计包含 施工 状态设备的队伍
        IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
        deviceReqVO.setDeptIds(new ArrayList<>(childDeptIds));
        List<IotDeviceDO> allRhDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
        Set<Long> haveDeviceDeptIds = new HashSet<>();
        if (CollUtil.isNotEmpty(allRhDevices)) {
            // 筛选出包含设备的队伍部门集合
            // 20260608 修改成 包含瑞恒主设备的 部门队伍id集合
            allRhDevices.forEach(device -> {
                if (mainDeviceCategoryIds.contains(device.getAssetClass())) {
                    haveDeviceDeptIds.add(device.getDeptId());
                }
            });
        }
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                // 项目部
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                // 队伍
                if ("3".equals(dept.getType())) {
                    teamDepartmentIds.add(dept.getId());
                }
            });
            // 遍历所有部门 只筛选出有设备的队伍
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId())) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDeptName) -> {
                        if (projectDeptId.equals(dept.getParentId()) && haveDeviceDeptIds.contains(deptId) && teamDepartmentIds.contains(deptId)) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
        }
        // 查询出指定时间区间内 已经填写的日报数量 存在注气时间是0 但是 注气量 不为0的情况
        // reqVO.setStatisticFlag("Y");
        List<IotRhDailyReportDO> dailyReports = iotRhDailyReportMapper.dailyReports(reqVO);
        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
        Map<Long, Integer> projectReportPair = new HashMap<>();
        // key项目部id     value项目部注气量
        Map<Long, BigDecimal> projectGasInjectionPair = new HashMap<>();
        if (CollUtil.isNotEmpty(dailyReports)) {
            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                if (CollUtil.isNotEmpty(projectTeamPair)) {
                    projectTeamPair.forEach((projectDeptId, teamDeptIds) -> {
                        if (teamDeptIds.contains(report.getDeptId())) {
                            if (report.getDailyGasInjection().compareTo(BigDecimal.ZERO)>0 || report.getDailyWaterInjection().compareTo(BigDecimal.ZERO)>0) {
                                // 项目部日报数量 20260608 统计 注气量 or 注水量 > 0 的日报数量
                                if (projectReportPair.containsKey(projectDeptId)) {
                                    Integer tempCount = projectReportPair.get(projectDeptId);
                                    projectReportPair.put(projectDeptId, ++tempCount);
                                } else {
                                    projectReportPair.put(projectDeptId, 1);
                                }
                            }
                            // 项目部 注气量
                            if (projectGasInjectionPair.containsKey(projectDeptId)) {
                                BigDecimal tempGasInjection = projectGasInjectionPair.get(projectDeptId);
                                BigDecimal subtotal = tempGasInjection.add(report.getDailyGasInjection());
                                projectGasInjectionPair.put(projectDeptId, subtotal);
                            } else {
                                projectGasInjectionPair.put(projectDeptId, report.getDailyGasInjection());
                            }
                        }
                    });
                }
            });
            // 计算指定时间区间内包含的天数
            long daysCount;
            if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                LocalDateTime start = reqVO.getCreateTime()[0];
                LocalDateTime end = reqVO.getCreateTime()[1];

                if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
                    // 使用ChronoUnit.DAYS.between计算天数差，并+1包含首尾两天
                    daysCount = ChronoUnit.DAYS.between(
                            start.toLocalDate(),
                            end.toLocalDate()
                    ) + 1;
                } else {
                    daysCount = 0L;
                }
            } else {
                daysCount = 0L;
            }
            // 计算每个项目部的设备利用率
            if (CollUtil.isNotEmpty(projectTeamPair)) {
                projectTeamPair.forEach((projectDeptId, teamIds) -> {
                    // 暂时不统计欧洲项目部 352
                    if (352 != projectDeptId) {
                        ProjectUtilizationRateVo rateVo = new ProjectUtilizationRateVo();
                        rateVo.setProjectDeptId(projectDeptId);
                        if (projectPair.containsKey(projectDeptId)) {
                            rateVo.setProjectDeptName(projectPair.get(projectDeptId));
                        }
                        if (allDeptPair.containsKey(projectDeptId)) {
                            DeptDO dept = allDeptPair.get(projectDeptId);
                            rateVo.setSort(dept.getSort());
                        }
                        // 设置每个项目部的注气量
                        if (projectGasInjectionPair.containsKey(projectDeptId)) {
                            BigDecimal gasInjection = projectGasInjectionPair.get(projectDeptId);
                            rateVo.setGasInjection(gasInjection);
                        }
                        // 遍历每个项目部 获取每个项目部下队伍数量
                        Integer currentTeamNum = teamIds.size();
                        rateVo.setTeamCount(currentTeamNum);
                        rateVo.setCumulativeDays(currentTeamNum * daysCount);
                        double rate = 0.0;
                        // 匹配出当前项目部下 日报数量
                        if (projectReportPair.containsKey(projectDeptId)) {
                            Integer reportCount = projectReportPair.getOrDefault(projectDeptId, 0);
                            rateVo.setConstructionDays(reportCount);
                            // 当前项目部 设备利用率 公式 reportCount/(currentTeamNum*daysCount)
                            // 计算设备利用率（处理除数为0的情况）
                            if (currentTeamNum > 0 && daysCount > 0) {
                                rate = new BigDecimal((double) reportCount / (currentTeamNum * daysCount))
                                        .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数，四舍五入
                                        .doubleValue();
                            }
                        }
                        rateVo.setUtilizationRate(rate); // 存储计算结果
                        rates.add(rateVo);
                    }
                });
            }
        }
        // rates.sort(Comparator.comparingDouble(ProjectUtilizationRateVo::getUtilizationRate).reversed());
        // 克拉玛依 加入到 吐哈项目部，两个项目部合并
        AtomicReference<Integer> mergeTeamCount = new AtomicReference<>(0);
        AtomicReference<Integer> mergeConstructionDays = new AtomicReference<>(0);
        AtomicReference<Long> mergeCumulativeDays = new AtomicReference<>(0l);
        rates.forEach(rate -> {
            // 克拉玛依 项目部数据
            if (rate.getProjectDeptId() == 166) {
                mergeTeamCount.set(rate.getTeamCount());
                mergeCumulativeDays.set(ObjUtil.isNotEmpty(rate.getCumulativeDays()) ? rate.getCumulativeDays() : 0);
                mergeConstructionDays.set(ObjUtil.isNotEmpty(rate.getConstructionDays()) ? rate.getConstructionDays() : 0);
            }
        });
        rates.forEach(rate -> {
            // 吐哈项目部 项目部数据
            if (rate.getProjectDeptId() == 160) {
                rate.setTeamCount((ObjUtil.isNotEmpty(rate.getTeamCount()) ? rate.getTeamCount() : 0) + mergeTeamCount.get());
                rate.setCumulativeDays((ObjUtil.isNotEmpty(rate.getCumulativeDays()) ? rate.getCumulativeDays() : 0l) + mergeCumulativeDays.get());
                rate.setConstructionDays((ObjUtil.isNotEmpty(rate.getConstructionDays()) ? rate.getConstructionDays() : 0) + mergeConstructionDays.get());
            }
        });
        // 删除projectDeptId为166的对象 克拉玛依项目部
        rates.removeIf(rate -> rate.getProjectDeptId() == 166);
        // 暂时不统计欧洲项目部 352
        rates.sort(Comparator.comparingInt(vo -> {
            Long deptId = vo.getProjectDeptId();
            // 获取当前projectDeptId在sortedProjectIds中的索引
            int index = sortedProjectIds.indexOf(deptId);
            // 若不在集合中，用集合长度作为索引（排在所有指定项目部之后）
            return index != -1 ? index : sortedProjectIds.size();
        }));
        return success(rates);
    }

    /**
     * 瑞恒 公司总体 设备利用率
     * @return
     */
    @GetMapping("/rh/device/totalUtilizationRate")
    @PermitAll
    public CommonResult<BigDecimal> totalUtilizationRate(IotRhDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 计算公司整体的设备利用率
        BigDecimal totalDeviceUtilization = BigDecimal.ZERO;

        List<Long> sortedProjectIds = new ArrayList<>();
        sortedProjectIds.add(164l); // 塔河项目部
        sortedProjectIds.add(165l); // 塔里木项目部
        sortedProjectIds.add(160l); // 吐哈项目部
        sortedProjectIds.add(256l); // 川庆项目部
        sortedProjectIds.add(269l); // 非洲项目部
        sortedProjectIds.add(273l); // 南美项目部
        sortedProjectIds.add(275l); // 中东项目部
        sortedProjectIds.add(282l); // 中亚项目部
        // 各项目部的设备利用率集合
        List<ProjectUtilizationRateVo> rates = new ArrayList<>();
        // 查询瑞恒 157l 所有项目部
        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(157l);
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // 队伍id 集合
        Set<Long> teamDepartmentIds = new HashSet<>();

        // 筛选瑞恒 主设备 rq_iot_rh_main_device_category
        Set<Long> mainDeviceCategoryIds = new HashSet<>();
        List<DictDataDO> constructionStatusDictData = dictDataService.getDictDataListByDictType("rq_iot_rh_main_device_category");
        if (CollUtil.isNotEmpty(constructionStatusDictData)) {
            constructionStatusDictData.forEach(data -> {
                String value = data.getValue();
                if (NumberUtil.isNumber(value)) {
                    Long longValue = Long.valueOf(value);
                    mainDeviceCategoryIds.add(longValue);
                }
            });
        }

        // 查询 瑞恒 所有设备 只统计包含 施工 状态设备的队伍
        IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
        deviceReqVO.setDeptIds(new ArrayList<>(childDeptIds));
        List<IotDeviceDO> allRhDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
        Set<Long> haveDeviceDeptIds = new HashSet<>();
        if (CollUtil.isNotEmpty(allRhDevices)) {
            // 筛选出包含设备的队伍部门集合
            // 20260608 修改成 包含瑞恒主设备的 部门队伍id集合
            allRhDevices.forEach(device -> {
                if (mainDeviceCategoryIds.contains(device.getAssetClass())) {
                    haveDeviceDeptIds.add(device.getDeptId());
                }
            });
        }
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                // 项目部
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                // 队伍
                if ("3".equals(dept.getType())) {
                    teamDepartmentIds.add(dept.getId());
                }
            });
            // 遍历所有部门 只筛选出有设备的队伍
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId())) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDeptName) -> {
                        if (projectDeptId.equals(dept.getParentId()) && haveDeviceDeptIds.contains(deptId) && teamDepartmentIds.contains(deptId)) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
        }
        // 查询出指定时间区间内 已经填写的日报数量 存在注气时间是0 但是 注气量 不为0的情况
        // reqVO.setStatisticFlag("Y");
        List<IotRhDailyReportDO> dailyReports = iotRhDailyReportMapper.dailyReports(reqVO);
        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
        Map<Long, Integer> projectReportPair = new HashMap<>();
        // key项目部id     value项目部注气量
        Map<Long, BigDecimal> projectGasInjectionPair = new HashMap<>();
        if (CollUtil.isNotEmpty(dailyReports)) {
            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                if (CollUtil.isNotEmpty(projectTeamPair)) {
                    projectTeamPair.forEach((projectDeptId, teamDeptIds) -> {
                        if (teamDeptIds.contains(report.getDeptId())) {
                            if (report.getDailyGasInjection().compareTo(BigDecimal.ZERO)>0 || report.getDailyWaterInjection().compareTo(BigDecimal.ZERO)>0) {
                                // 项目部日报数量 20260608 统计 注气量 or 注水量 > 0 的日报数量
                                if (projectReportPair.containsKey(projectDeptId)) {
                                    Integer tempCount = projectReportPair.get(projectDeptId);
                                    projectReportPair.put(projectDeptId, ++tempCount);
                                } else {
                                    projectReportPair.put(projectDeptId, 1);
                                }
                            }
                            // 项目部 注气量
                            if (projectGasInjectionPair.containsKey(projectDeptId)) {
                                BigDecimal tempGasInjection = projectGasInjectionPair.get(projectDeptId);
                                BigDecimal subtotal = tempGasInjection.add(report.getDailyGasInjection());
                                projectGasInjectionPair.put(projectDeptId, subtotal);
                            } else {
                                projectGasInjectionPair.put(projectDeptId, report.getDailyGasInjection());
                            }
                        }
                    });
                }
            });
            // 计算指定时间区间内包含的天数
            long daysCount;
            if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                LocalDateTime start = reqVO.getCreateTime()[0];
                LocalDateTime end = reqVO.getCreateTime()[1];

                if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
                    // 使用ChronoUnit.DAYS.between计算天数差，并+1包含首尾两天
                    daysCount = ChronoUnit.DAYS.between(
                            start.toLocalDate(),
                            end.toLocalDate()
                    ) + 1;
                } else {
                    daysCount = 0L;
                }
            } else {
                daysCount = 0L;
            }

            //时间查询区间内 公司总的日报数量
            Integer totalReportCount = 0;
            // 时间查询区间内 公司总的队伍数量
            Integer totalTeamNum = 0;

            // 计算每个项目部的设备利用率
            if (CollUtil.isNotEmpty(projectTeamPair)) {
                for (Map.Entry<Long, Set<Long>> longSetEntry : projectTeamPair.entrySet()) {
                    Long projectDeptId = longSetEntry.getKey();
                    Set<Long> teamIds = longSetEntry.getValue();
                    Integer currentTeamNum = teamIds.size();
                    totalTeamNum = totalTeamNum + currentTeamNum;
                    if (projectReportPair.containsKey(projectDeptId)) {
                        Integer reportCount = projectReportPair.getOrDefault(projectDeptId, 0);
                        totalReportCount = totalReportCount + reportCount;
                        // 公司总的 设备利用率 公式 totalReportCount/(totalTeamNum*daysCount)
                    }
                }
                // 计算公司总的设备利用率
                if (totalTeamNum > 0 && daysCount > 0) {
                    totalDeviceUtilization = new BigDecimal((double) totalReportCount / (totalTeamNum * daysCount))
                            .setScale(4, RoundingMode.HALF_UP);
                }
            }
        }
        return success(totalDeviceUtilization);
    }

    /**
     * 瑞恒 设备利用率 按 队伍 统计
     * @return
     */
    @GetMapping("/rh/device/teamUtilizationRate")
    @PermitAll
    public CommonResult<List<TeamUtilizationRateVo>> teamUtilizationRate(IotRhDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 必须传递 项目部id 查询队伍数据
        if (ObjUtil.isEmpty(reqVO.getDeptId())) {
            throw exception(IOT_DAILY_REPORT_DEPT_NOT_EXISTS);
        }

        // 指定项目部的各队伍设备利用率集合
        List<TeamUtilizationRateVo> rates = new ArrayList<>();

        // 查询指定项目部下的 队伍集合
        DeptListReqVO deptReqVO = new DeptListReqVO();
        deptReqVO.setDeptId(reqVO.getDeptId());
        List<DeptDO> projectTeams = deptService.getDeptListByParentId(deptReqVO);

        // 指定项目部下的 队伍id集合
        Set<Long> projectTeamIds = new HashSet<>();
        if (CollUtil.isNotEmpty(projectTeams)) {
            projectTeams.forEach(team -> {
                if ("3".equals(team.getType())) {
                    projectTeamIds.add(team.getId());
                }
            });
            // 如果是吐哈 将克拉玛依的队伍合并过来
            if (160 == reqVO.getDeptId()) {
                deptReqVO.setDeptId(166l);
                List<DeptDO> klmyTeams = deptService.getDeptListByParentId(deptReqVO);
                if (CollUtil.isNotEmpty(klmyTeams)) {
                    klmyTeams.forEach(team -> {
                        projectTeamIds.add(team.getId());
                    });
                }
            }
        }

        // 筛选瑞恒 主设备 rq_iot_rh_main_device_category
        Set<Long> mainDeviceCategoryIds = new HashSet<>();
        List<DictDataDO> constructionStatusDictData = dictDataService.getDictDataListByDictType("rq_iot_rh_main_device_category");
        if (CollUtil.isNotEmpty(constructionStatusDictData)) {
            constructionStatusDictData.forEach(data -> {
                String value = data.getValue();
                if (NumberUtil.isNumber(value)) {
                    Long longValue = Long.valueOf(value);
                    mainDeviceCategoryIds.add(longValue);
                }
            });
        }

        // 查询 项目部下 包含 施工 状态设备的队伍
        IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
        deviceReqVO.setDeptIds(new ArrayList<>(projectTeamIds));
        List<IotDeviceDO> allRhDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
        Set<Long> haveDeviceDeptIds = new HashSet<>();
        if (CollUtil.isNotEmpty(allRhDevices)) {
            // 筛选出包含设备的队伍部门集合
            allRhDevices.forEach(device -> {
                if (mainDeviceCategoryIds.contains(device.getAssetClass())) {
                    haveDeviceDeptIds.add(device.getDeptId());
                }
            });
        }

        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(projectTeamIds);

        // 求 projectTeamIds 与 haveDeviceDeptIds 的交集
        Set<Long> intersectionTeamIds = new HashSet<>();
        if (CollUtil.isNotEmpty(projectTeamIds)) {
            projectTeamIds.forEach(teamId -> {
                if (haveDeviceDeptIds.contains(teamId)) {
                    intersectionTeamIds.add(teamId);
                }
            });
        }

        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key队伍id   value队伍名称
        Map<Long, String> teamPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // key队伍id   value队伍日报数量
        Map<Long, Long> teamReportCountPair = new HashMap<>();
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                teamPair.put(deptId, dept.getName());
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId())) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
        }
        if (CollUtil.isNotEmpty(intersectionTeamIds)) {
            // 查询出指定时间区间内 指定队伍id集合 已经填写的日报数量
            reqVO.setDeptIds(intersectionTeamIds);
            // reqVO.setStatisticFlag("Y");
            List<IotRhDailyReportDO> dailyReports = iotRhDailyReportMapper.dailyReports(reqVO);
            // 筛选出每个队伍的日报
            if (CollUtil.isNotEmpty(dailyReports)) {
                // 整理出每个项队伍填报的日报数量
                dailyReports.forEach(report -> {
                    if (teamReportCountPair.containsKey(report.getDeptId())) {
                        Long tempCount = teamReportCountPair.get(report.getDeptId());
                        teamReportCountPair.put(report.getDeptId(), ++tempCount);
                    } else {
                        teamReportCountPair.put(report.getDeptId(), 1l);
                    }
                });
                // 计算指定时间区间内包含的天数
                long daysCount;
                if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                    LocalDateTime start = reqVO.getCreateTime()[0];
                    LocalDateTime end = reqVO.getCreateTime()[1];

                    if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
                        // 使用ChronoUnit.DAYS.between计算天数差，并+1包含首尾两天
                        daysCount = ChronoUnit.DAYS.between(
                                start.toLocalDate(),
                                end.toLocalDate()
                        ) + 1;
                    } else {
                        daysCount = 0L;
                    }
                } else {
                    daysCount = 0L;
                }
                // 计算每个队伍的设备利用率
                if (CollUtil.isNotEmpty(intersectionTeamIds)) {
                    intersectionTeamIds.forEach(teamId -> {
                        TeamUtilizationRateVo rateVo = new TeamUtilizationRateVo();
                        rateVo.setProjectDeptId(reqVO.getDeptId());
                        rateVo.setTeamId(teamId);
                        rateVo.setCumulativeDays(daysCount);
                        if (teamPair.containsKey(teamId)) {
                            rateVo.setTeamName(teamPair.get(teamId));
                        }
                        // 匹配出当前小队 日报数量
                        Long reportCount = 0l;
                        if (teamReportCountPair.containsKey(teamId)) {
                            reportCount = teamReportCountPair.getOrDefault(teamId, 0l);
                            rateVo.setConstructionDays(reportCount);
                        }
                        // 当前小队 设备利用率 公式 reportCount/daysCount
                        // 计算设备利用率（处理除数为0的情况）
                        double rate = 0.0;
                        if (reportCount > 0 && daysCount > 0) {
                            rate = new BigDecimal((double) reportCount /  daysCount)
                                    .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数，四舍五入
                                    .doubleValue();;
                        }
                        rateVo.setUtilizationRate(rate); // 存储计算结果
                        rates.add(rateVo);
                    });
                }
            }
        }
        rates.sort(Comparator.comparingDouble(TeamUtilizationRateVo::getUtilizationRate).reversed());
        return success(rates);
    }

    /**
     * 瑞鹰 设备利用率 按项目部统计
     * @return
     */
    @GetMapping("/ry/device/utilizationRate")
    @PermitAll
    public CommonResult<List<ProjectUtilizationRateVo>> ryUtilizationRate(IotRyDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 各项目部的设备利用率集合
        List<ProjectUtilizationRateVo> rates = new ArrayList<>();
        // 查询瑞鹰 158l 所有项目部
        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(158l);
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // 队伍id 集合
        Set<Long> crewIds = new HashSet<>();
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                if ("3".equals(dept.getType())) {
                    // 队伍
                    crewIds.add(dept.getId());
                }
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId()) && 0==dept.getStatus()) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
        }
        // 查询出指定时间区间内 已经填写的日报数量
        // 瑞鹰区分 钻井 修井 日报
        // 钻井：日报状态 过滤掉 ‘等停dt’    修井：日报状态过滤掉 ‘等停dt’、‘整修zx’
        List<String> statuses = new ArrayList<>();
        statuses.add("dt");
        statuses.add("zx");
        reqVO.setStatuses(statuses);
        List<IotRyDailyReportDO> dailyReports = iotRyDailyReportMapper.dailyReports(reqVO);
        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
        Map<Long, Integer> projectReportPair = new HashMap<>();
        if (CollUtil.isNotEmpty(dailyReports)) {
            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                if (CollUtil.isNotEmpty(projectTeamPair)) {
                    projectTeamPair.forEach((projectDeptId, teamDeptIds) -> {
                        if (teamDeptIds.contains(report.getDeptId())) {
                            if (projectReportPair.containsKey(projectDeptId)) {
                                Integer tempCount = projectReportPair.get(projectDeptId);
                                projectReportPair.put(projectDeptId, ++tempCount);
                            } else {
                                projectReportPair.put(projectDeptId, 1);
                            }
                        }
                    });
                }

            });
            // 计算指定时间区间内包含的天数
            long daysCount;
            if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                LocalDateTime start = reqVO.getCreateTime()[0];
                LocalDateTime end = reqVO.getCreateTime()[1];
                if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
                    // 使用ChronoUnit.DAYS.between计算天数差，并+1包含首尾两天
                    daysCount = ChronoUnit.DAYS.between(
                            start.toLocalDate(),
                            end.toLocalDate()
                    ) + 1;
                } else {
                    daysCount = 0L;
                }
            } else {
                daysCount = 0L;
            }
            // 计算每个项目部的设备利用率
            if (CollUtil.isNotEmpty(projectTeamPair)) {
                projectTeamPair.forEach((projectDeptId, teamIds) -> {
                    ProjectUtilizationRateVo rateVo = new ProjectUtilizationRateVo();
                    rateVo.setProjectDeptId(projectDeptId);
                    if (projectPair.containsKey(projectDeptId)) {
                        rateVo.setProjectDeptName(projectPair.get(projectDeptId));
                    }
                    // 遍历每个项目部 获取每个项目部下队伍数量
                    Integer currentTeamNum = teamIds.size();
                    rateVo.setTeamCount(currentTeamNum);
                    rateVo.setCumulativeDays(currentTeamNum * daysCount);
                    double rate = 0.0;
                    // 匹配出当前项目部下 日报数量
                    if (projectReportPair.containsKey(projectDeptId)) {
                        Integer reportCount = projectReportPair.getOrDefault(projectDeptId, 0);
                        rateVo.setConstructionDays(reportCount);
                        // 当前项目部 设备利用率 公式 reportCount/(currentTeamNum*daysCount)
                        // 计算设备利用率（处理除数为0的情况）
                        if (currentTeamNum > 0 && daysCount > 0) {
                            rate = new BigDecimal((double) reportCount / (currentTeamNum * daysCount))
                                    .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数，四舍五入
                                    .doubleValue();;
                        }
                    }
                    rateVo.setUtilizationRate(rate); // 存储计算结果
                    rates.add(rateVo);
                });
            }
        }
        rates.sort(Comparator.comparingDouble(ProjectUtilizationRateVo::getUtilizationRate).reversed());
        return success(rates);
    }

    /**
     * 瑞鹰 公司总的设备利用率
     * @return
     */
    @GetMapping("/ry/device/totalUtilizationRate")
    @PermitAll
    public CommonResult<BigDecimal> totalUtilizationRate(IotRyDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 计算公司整体的设备利用率
        BigDecimal totalDeviceUtilization = BigDecimal.ZERO;
        // 查询瑞鹰 158l 所有项目部
        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(158l);
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // 队伍id 集合
        Set<Long> crewIds = new HashSet<>();
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                if ("3".equals(dept.getType())) {
                    // 队伍
                    crewIds.add(dept.getId());
                }
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId()) && 0==dept.getStatus()) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
        }
        // 查询出指定时间区间内 已经填写的日报数量
        // 瑞鹰区分 钻井 修井 日报
        // 钻井：日报状态 过滤掉 ‘等停dt’    修井：日报状态过滤掉 ‘等停dt’、‘整修zx’
        List<String> statuses = new ArrayList<>();
        statuses.add("dt");
        statuses.add("zx");
        reqVO.setStatuses(statuses);
        List<IotRyDailyReportDO> dailyReports = iotRyDailyReportMapper.dailyReports(reqVO);
        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
        Map<Long, Integer> projectReportPair = new HashMap<>();
        if (CollUtil.isNotEmpty(dailyReports)) {
            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                if (CollUtil.isNotEmpty(projectTeamPair)) {
                    projectTeamPair.forEach((projectDeptId, teamDeptIds) -> {
                        if (teamDeptIds.contains(report.getDeptId())) {
                            if (projectReportPair.containsKey(projectDeptId)) {
                                Integer tempCount = projectReportPair.get(projectDeptId);
                                projectReportPair.put(projectDeptId, ++tempCount);
                            } else {
                                projectReportPair.put(projectDeptId, 1);
                            }
                        }
                    });
                }

            });
            // 计算指定时间区间内包含的天数
            long daysCount;
            if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                LocalDateTime start = reqVO.getCreateTime()[0];
                LocalDateTime end = reqVO.getCreateTime()[1];
                if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
                    // 使用ChronoUnit.DAYS.between计算天数差，并+1包含首尾两天
                    daysCount = ChronoUnit.DAYS.between(
                            start.toLocalDate(),
                            end.toLocalDate()
                    ) + 1;
                } else {
                    daysCount = 0L;
                }
            } else {
                daysCount = 0L;
            }

            //时间查询区间内 公司总的日报数量
            Integer totalReportCount = 0;
            // 时间查询区间内 公司总的队伍数量
            Integer totalTeamNum = 0;
            if (CollUtil.isNotEmpty(projectTeamPair)) {
                for (Map.Entry<Long, Set<Long>> longSetEntry : projectTeamPair.entrySet()) {
                    Long projectDeptId = longSetEntry.getKey();
                    Set<Long> teamIds = longSetEntry.getValue();
                    Integer currentTeamNum = teamIds.size();
                    totalTeamNum = totalTeamNum + currentTeamNum;
                    if (projectReportPair.containsKey(projectDeptId)) {
                        Integer reportCount = projectReportPair.getOrDefault(projectDeptId, 0);
                        totalReportCount = totalReportCount + reportCount;
                        // 公司总的 设备利用率 公式 totalReportCount/(totalTeamNum*daysCount)
                    }
                }
                // 计算公司总的设备利用率
                if (totalTeamNum > 0 && daysCount > 0) {
                    totalDeviceUtilization = new BigDecimal((double) totalReportCount / (totalTeamNum * daysCount))
                            .setScale(4, RoundingMode.HALF_UP);
                }
            }
        }
        return success(totalDeviceUtilization);
    }

    /**
     * 瑞鹰 NPT 队伍数量
     * @return
     */
    @GetMapping("/ry/device/nptCount")
    @PermitAll
    public CommonResult<List<NptCountVo>> nptCount(IotRyDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 计算公司整体的设备利用率
        BigDecimal totalDeviceUtilization = BigDecimal.ZERO;
        // 查询瑞鹰 158l 所有项目部
        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(158l);
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // 队伍id 集合
        Set<Long> crewIds = new HashSet<>();
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                if ("3".equals(dept.getType())) {
                    // 队伍
                    crewIds.add(dept.getId());
                }
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId()) && 0==dept.getStatus()) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
        }
        // 查询出指定时间区间内 已经填写的日报数量
        // 瑞鹰区分 钻井 修井 日报
        List<String> statuses = new ArrayList<>();
        // statuses.add("dt");
        // statuses.add("zx");
        reqVO.setStatuses(statuses);
        List<IotRyDailyReportDO> dailyReports = iotRyDailyReportMapper.dailyReports(reqVO);
        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
        Map<Long, Integer> projectReportPair = new HashMap<>();
        // 过滤掉 ‘设备保养、生产配合、待命’ 之外的非生产时间集合
        Map<String, Integer> nptTeamPair = new HashMap<>();
        List<NptCountVo> resultNptCounts = new ArrayList<>();
        if (CollUtil.isNotEmpty(dailyReports)) {
            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                if (CollUtil.isNotEmpty(projectTeamPair)) {
                    projectTeamPair.forEach((projectDeptId, teamDeptIds) -> {
                        if (teamDeptIds.contains(report.getDeptId())) {
                            /* if (projectReportPair.containsKey(projectDeptId)) {
                                Integer tempCount = projectReportPair.get(projectDeptId);
                                projectReportPair.put(projectDeptId, ++tempCount);
                            } else {
                                projectReportPair.put(projectDeptId, 1);
                            } */
                            // 统计日报下的非生产时间集合
                            BigDecimal accidentTime = report.getAccidentTime();
                            if (ObjUtil.isNotEmpty(accidentTime) && accidentTime.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("工程质量")) {
                                    Integer tempCount = nptTeamPair.get("工程质量");
                                    nptTeamPair.put("工程质量", ++tempCount);
                                } else {
                                    nptTeamPair.put("工程质量", 1);
                                }
                            }
                            BigDecimal repairTime = report.getRepairTime();
                            if (ObjUtil.isNotEmpty(repairTime) && repairTime.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("设备故障")) {
                                    Integer tempCount = nptTeamPair.get("设备故障");
                                    nptTeamPair.put("设备故障", ++tempCount);
                                } else {
                                    nptTeamPair.put("设备故障", 1);
                                }
                            }
                            BigDecimal complexityTime = report.getComplexityTime();
                            if (ObjUtil.isNotEmpty(complexityTime) && complexityTime.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("技术受限")) {
                                    Integer tempCount = nptTeamPair.get("技术受限");
                                    nptTeamPair.put("技术受限", ++tempCount);
                                } else {
                                    nptTeamPair.put("技术受限", 1);
                                }
                            }
                            BigDecimal rectificationTime = report.getRectificationTime();
                            if (ObjUtil.isNotEmpty(rectificationTime) && rectificationTime.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("生产组织")) {
                                    Integer tempCount = nptTeamPair.get("生产组织");
                                    nptTeamPair.put("生产组织", ++tempCount);
                                } else {
                                    nptTeamPair.put("生产组织", 1);
                                }
                            }
                            BigDecimal waitingStopTime = report.getWaitingStopTime();
                            if (ObjUtil.isNotEmpty(waitingStopTime) && waitingStopTime.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("不可抗力")) {
                                    Integer tempCount = nptTeamPair.get("不可抗力");
                                    nptTeamPair.put("不可抗力", ++tempCount);
                                } else {
                                    nptTeamPair.put("不可抗力", 1);
                                }
                            }
                            BigDecimal partyaDesign = report.getPartyaDesign();
                            if (ObjUtil.isNotEmpty(partyaDesign) && partyaDesign.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("甲方设计")) {
                                    Integer tempCount = nptTeamPair.get("甲方设计");
                                    nptTeamPair.put("甲方设计", ++tempCount);
                                } else {
                                    nptTeamPair.put("甲方设计", 1);
                                }
                            }
                            BigDecimal partyaPrepare = report.getPartyaPrepare();
                            if (ObjUtil.isNotEmpty(partyaPrepare) && partyaPrepare.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("甲方准备")) {
                                    Integer tempCount = nptTeamPair.get("甲方准备");
                                    nptTeamPair.put("甲方准备", ++tempCount);
                                } else {
                                    nptTeamPair.put("甲方准备", 1);
                                }
                            }
                            BigDecimal partyaResource = report.getPartyaResource();
                            if (ObjUtil.isNotEmpty(partyaResource) && partyaResource.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("甲方资源")) {
                                    Integer tempCount = nptTeamPair.get("甲方资源");
                                    nptTeamPair.put("甲方资源", ++tempCount);
                                } else {
                                    nptTeamPair.put("甲方资源", 1);
                                }
                            }
                            BigDecimal otherNptTime = report.getOtherNptTime();
                            if (ObjUtil.isNotEmpty(otherNptTime) && otherNptTime.compareTo(BigDecimal.ZERO)>0) {
                                if (nptTeamPair.containsKey("其它非生产时间")) {
                                    Integer tempCount = nptTeamPair.get("其它非生产时间");
                                    nptTeamPair.put("其它非生产时间", ++tempCount);
                                } else {
                                    nptTeamPair.put("其它非生产时间", 1);
                                }
                            }
                        }
                    });
                }
            });

            if (CollUtil.isNotEmpty(nptTeamPair)) {
                nptTeamPair.forEach((nptName, teamCount) -> {
                    NptCountVo countVo = new NptCountVo();
                    countVo.setNptName(nptName);
                    countVo.setTeamCount(teamCount);
                    resultNptCounts.add(countVo);
                });
            }
        }
        // 按照每种非生产时间队伍数量 降序排列
        resultNptCounts.sort(Comparator.comparingInt(NptCountVo::getTeamCount).reversed());
        return success(resultNptCounts);
    }

    /**
     * 瑞鹰 设备利用率 按 队伍 统计
     * @return
     */
    @GetMapping("/ry/device/teamUtilizationRate")
    @PermitAll
    public CommonResult<List<TeamUtilizationRateVo>> ryTeamUtilizationRate(IotRyDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 必须传递 项目部id 查询队伍数据
        if (ObjUtil.isEmpty(reqVO.getDeptId())) {
            throw exception(IOT_DAILY_REPORT_DEPT_NOT_EXISTS);
        }

        // 指定项目部的各队伍设备利用率集合
        List<TeamUtilizationRateVo> rates = new ArrayList<>();

        // 查询指定项目部下的 队伍集合
        DeptListReqVO deptReqVO = new DeptListReqVO();
        deptReqVO.setDeptId(reqVO.getDeptId());
        List<DeptDO> projectTeams = deptService.getDeptListByParentId(deptReqVO);
        // 指定项目部下的 队伍id集合
        Set<Long> projectTeamIds = new HashSet<>();
        if (CollUtil.isNotEmpty(projectTeams)) {
            projectTeams.forEach(team -> {
                if ("3".equals(team.getType())) {
                    projectTeamIds.add(team.getId());
                }
            });
        }

        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(projectTeamIds);

        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key队伍id   value队伍名称
        Map<Long, String> teamPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // key队伍id   value队伍日报数量
        Map<Long, Long> teamReportCountPair = new HashMap<>();
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if (dept.getName().contains("项目部") ) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                teamPair.put(deptId, dept.getName());
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId())) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
        }
        if (CollUtil.isNotEmpty(projectTeamIds)) {
            // 查询出指定时间区间内 指定队伍id集合 已经填写的日报数量
            reqVO.setDeptIds(projectTeamIds);
            // 瑞鹰区分 钻井 修井 日报
            // 钻井：日报状态 过滤掉 ‘等停dt’    修井：日报状态过滤掉 ‘等停dt’、‘整修zx’
            List<String> statuses = new ArrayList<>();
            statuses.add("dt");
            statuses.add("zx");
            reqVO.setStatuses(statuses);
            List<IotRyDailyReportDO> dailyReports = iotRyDailyReportMapper.dailyReports(reqVO);
            // 筛选出每个队伍的日报
            if (CollUtil.isNotEmpty(dailyReports)) {
                // 整理出每个项队伍填报的日报数量
                dailyReports.forEach(report -> {
                    if (teamReportCountPair.containsKey(report.getDeptId())) {
                        Long tempCount = teamReportCountPair.get(report.getDeptId());
                        teamReportCountPair.put(report.getDeptId(), ++tempCount);
                    } else {
                        teamReportCountPair.put(report.getDeptId(), 1l);
                    }
                });
                // 计算指定时间区间内包含的天数
                long daysCount;
                if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                    LocalDateTime start = reqVO.getCreateTime()[0];
                    LocalDateTime end = reqVO.getCreateTime()[1];
                    if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
                        // 使用ChronoUnit.DAYS.between计算天数差，并+1包含首尾两天
                        daysCount = ChronoUnit.DAYS.between(
                                start.toLocalDate(),
                                end.toLocalDate()
                        ) + 1;
                    } else {
                        daysCount = 0L;
                    }
                } else {
                    daysCount = 0L;
                }
                // 计算每个队伍的设备利用率
                if (CollUtil.isNotEmpty(projectTeamIds)) {
                    projectTeamIds.forEach(teamId -> {
                        TeamUtilizationRateVo rateVo = new TeamUtilizationRateVo();
                        rateVo.setProjectDeptId(reqVO.getDeptId());
                        rateVo.setTeamId(teamId);
                        rateVo.setCumulativeDays(daysCount);
                        if (teamPair.containsKey(teamId)) {
                            rateVo.setTeamName(teamPair.get(teamId));
                        }
                        // 匹配出当前小队 日报数量
                        Long reportCount = 0l;
                        if (teamReportCountPair.containsKey(teamId)) {
                            reportCount = teamReportCountPair.getOrDefault(teamId, 0l);
                            rateVo.setConstructionDays(reportCount);
                        }
                        // 当前小队 设备利用率 公式 reportCount/daysCount
                        // 计算设备利用率（处理除数为0的情况）
                        double rate = 0.0;
                        if (reportCount > 0 && daysCount > 0) {
                            rate = new BigDecimal((double) reportCount /  daysCount)
                                    .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数，四舍五入
                                    .doubleValue();;
                        }
                        rateVo.setUtilizationRate(rate); // 存储计算结果
                        rates.add(rateVo);
                    });
                }
            }
        }
        rates.sort(Comparator.comparingDouble(TeamUtilizationRateVo::getUtilizationRate).reversed());
        return success(rates);
    }

    /**
     * 瑞都 设备利用率 按 项目部 统计
     * @return
     */
    @GetMapping("/rd/device/utilizationRate")
    @PermitAll
    public CommonResult<List<ProjectUtilizationRateVo>> rdUtilizationRate(IotRdDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 各项目部的设备利用率集合
        List<ProjectUtilizationRateVo> rates = new ArrayList<>();
        // 查询瑞都 163l 所有项目部
        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(163l);
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // 设备ID到其所属部门ID的映射
        Map<Long, Long> deviceIdToDeptIdMap = new HashMap<>();
        // key项目部id     value项目部下包含的队伍的 压裂 连油 设备数量
        Map<Long, Integer> projectDevicePair = new HashMap<>();
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if (dept.getName().contains("项目部") ) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId())) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
            // 查询不同项目部下 包含的 压裂泵车26 连油主车设备31
            // 查询 连油主车 或 压裂泵车 相应的设备类别 id集合
            Set<Long> utilizeDeviceCategoryIds = new HashSet<>();
            IotProductClassifyListReqVO categoryReqVO = new IotProductClassifyListReqVO();
            categoryReqVO.setName("连油主车");
            List<IotProductClassifyDO> deviceCategories = iotProductClassifyMapper.selectList(categoryReqVO);
            if (CollUtil.isNotEmpty(deviceCategories)) {
                utilizeDeviceCategoryIds.add(deviceCategories.get(0).getId());
            }
            // 查询 压裂泵车 的设备类别
            categoryReqVO.setName("压裂泵车");
            List<IotProductClassifyDO> pumpCategories = iotProductClassifyMapper.selectList(categoryReqVO);
            if (CollUtil.isNotEmpty(pumpCategories)) {
                pumpCategories.forEach(category -> {
                    utilizeDeviceCategoryIds.add(category.getId());
                });
            }
            IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
            deviceReqVO.setAssetClasses(new ArrayList<>(utilizeDeviceCategoryIds));
            List<IotDeviceDO> utilizeDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
            // 筛选出项目部下包含的队伍的设备数量

            Set<Long> deviceIds = new HashSet<>();

            if (CollUtil.isNotEmpty(utilizeDevices)) {
                utilizeDevices.forEach(device -> {
                    // 存储设备ID与所属部门ID的映射
                    deviceIdToDeptIdMap.put(device.getId(), device.getDeptId());
                    // 筛选出各项目部下的 压裂 连油 设备
                    projectTeamPair.forEach((projectId, teamIds) -> {
                        if (projectId.equals(device.getDeptId()) || teamIds.contains(device.getDeptId())) {
                            if (projectDevicePair.containsKey(projectId)) {
                                Integer tempCount = projectDevicePair.get(projectId);
                                projectDevicePair.put(projectId, ++tempCount);
                            } else {
                                projectDevicePair.put(projectId, 1);
                            }
                            // 找出各项目部下的设备id集合 用来查询日报
                            deviceIds.add(device.getId());
                        }
                    });
                });
            }
        }
        // 查询出指定时间区间内 已经填写的日报 再根据设备id 进行筛选 通过设备id 建立项目部 与 日报数量之间的关联
        // 判断日报中 device_ids 字段中每个设备 是否属于需要统计的 压裂 连油 设备
        List<IotRdDailyReportDO> dailyReports = iotRdDailyReportMapper.dailyReports(reqVO);
        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
        Map<Long, Integer> projectReportPair = new HashMap<>();
        if (CollUtil.isNotEmpty(dailyReports)) {
            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                if (CollUtil.isNotEmpty(projectTeamPair)) {
                    projectTeamPair.forEach((projectDeptId, teamDeptIds) -> {
                        Set<Long> tempDeviceIds = report.getDeviceIds();
                        // 判断 集合 tempDeviceIds 中的任意的 ‘设备id’ 是否包含在 集合 teamDeptIds 中
                        // 判断tempDeviceIds中的任意设备所属部门是否在当前项目部的队伍部门中
                        boolean hasMatchingDevice = CollUtil.isNotEmpty(tempDeviceIds) && tempDeviceIds.stream()
                                .map(deviceIdToDeptIdMap::get) // 通过映射表获取设备所属部门ID
                                .filter(Objects::nonNull) // 过滤掉非统计范围内的设备（避免空指针）
                                .anyMatch(teamDeptIds::contains); // 任意设备所属部门在队伍部门中则匹配
                        if (hasMatchingDevice) {
                            if (projectReportPair.containsKey(projectDeptId)) {
                                Integer tempCount = projectReportPair.get(projectDeptId);
                                projectReportPair.put(projectDeptId, ++tempCount);
                            } else {
                                projectReportPair.put(projectDeptId, 1);
                            }
                        }
                    });
                }
            });
            // 计算指定时间区间内包含的天数
            long daysCount;
            if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                LocalDateTime start = reqVO.getCreateTime()[0];
                LocalDateTime end = reqVO.getCreateTime()[1];
                if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
                    // 使用ChronoUnit.DAYS.between计算天数差，并+1包含首尾两天
                    daysCount = ChronoUnit.DAYS.between(
                            start.toLocalDate(),
                            end.toLocalDate()
                    ) + 1;
                } else {
                    daysCount = 0L;
                }
            } else {
                daysCount = 0L;
            }
            // 计算每个项目部的设备利用率
            if (CollUtil.isNotEmpty(projectDevicePair)) {
                projectDevicePair.forEach((projectDeptId, deviceNum) -> {
                    ProjectUtilizationRateVo rateVo = new ProjectUtilizationRateVo();
                    rateVo.setProjectDeptId(projectDeptId);
                    if (projectPair.containsKey(projectDeptId)) {
                        rateVo.setProjectDeptName(projectPair.get(projectDeptId));
                    }
                    // 遍历每个项目部 获取每个项目部下 压裂 连油 设备数量
                    rateVo.setTeamCount(deviceNum);
                    rateVo.setCumulativeDays(deviceNum * daysCount);
                    double rate = 0.0;
                    // 匹配出当前项目部下 日报数量
                    if (projectReportPair.containsKey(projectDeptId)) {
                        Integer reportCount = projectReportPair.getOrDefault(projectDeptId, 0);
                        rateVo.setConstructionDays(reportCount);
                        // 当前项目部 设备利用率 公式 reportCount/(currentTeamNum*daysCount)
                        // 计算设备利用率（处理除数为0的情况）
                        if (deviceNum > 0 && daysCount > 0) {
                            rate = new BigDecimal((double) reportCount / (deviceNum * daysCount))
                                    .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数，四舍五入
                                    .doubleValue();;
                        }
                    }
                    rateVo.setUtilizationRate(rate); // 存储计算结果
                    rates.add(rateVo);
                });
            }
        }
        // 将返回列表中的 部门名称 去除多语言标识
        // 处理projectDeptName，截取~~首次出现前的字符串
        if (CollUtil.isNotEmpty(rates)) {
            rates.forEach(rateVo -> {
                String originalName = rateVo.getProjectDeptName();
                if (StrUtil.isNotBlank(originalName) && originalName.contains("~~")) {
                    // 截取首次~~之前的部分
                    String processedName = originalName.substring(0, originalName.indexOf("~~"));
                    rateVo.setProjectDeptName(processedName);
                }
                // 空值或无~~标识时，保留原名称
            });
        }
        // 日报应用前先模拟数据
        rates.clear();
        ProjectUtilizationRateVo ylk = new ProjectUtilizationRateVo();
        ylk.setProjectDeptId(331l);
        ylk.setProjectDeptName("伊拉克项目部");
        ylk.setTeamCount(4);
        ylk.setCumulativeDays(1216l);
        ylk.setConstructionDays(646);
        ylk.setUtilizationRate(0.5313);
        ProjectUtilizationRateVo xj = new ProjectUtilizationRateVo();
        xj.setProjectDeptId(329l);
        xj.setProjectDeptName("新疆项目部");
        xj.setTeamCount(2);
        xj.setCumulativeDays(852l);
        xj.setConstructionDays(387);
        xj.setUtilizationRate(0.4542);
        ProjectUtilizationRateVo db = new ProjectUtilizationRateVo();
        db.setProjectDeptId(326l);
        db.setProjectDeptName("东部项目部");
        db.setTeamCount(3);
        db.setCumulativeDays(912l);
        db.setConstructionDays(261);
        db.setUtilizationRate(0.2862);
        ProjectUtilizationRateVo qh = new ProjectUtilizationRateVo();
        qh.setProjectDeptId(327l);
        qh.setProjectDeptName("青海项目部");
        qh.setTeamCount(1);
        qh.setCumulativeDays(304l);
        qh.setConstructionDays(179);
        qh.setUtilizationRate(0.5888);
        ProjectUtilizationRateVo xnyl = new ProjectUtilizationRateVo();
        xnyl.setProjectDeptId(325l);
        xnyl.setProjectDeptName("西南压裂项目部");
        xnyl.setTeamCount(1);
        xnyl.setCumulativeDays(304l);
        xnyl.setConstructionDays(252);
        xnyl.setUtilizationRate(0.8289);
        ProjectUtilizationRateVo xnly = new ProjectUtilizationRateVo();
        xnly.setProjectDeptId(330l);
        xnly.setProjectDeptName("西南连续油管项目部");
        xnly.setTeamCount(3);
        xnly.setCumulativeDays(912l);
        xnly.setConstructionDays(443);
        xnly.setUtilizationRate(0.4857);
        ProjectUtilizationRateVo lby = new ProjectUtilizationRateVo();
        lby.setProjectDeptId(349l);
        lby.setProjectDeptName("利比亚项目部");
        lby.setTeamCount(1);
        lby.setCumulativeDays(304l);
        lby.setConstructionDays(21);
        lby.setUtilizationRate(0.0691);
        rates.add(ylk);
        rates.add(xj);
        rates.add(db);
        rates.add(qh);
        rates.add(xnyl);
        rates.add(xnly);
        rates.add(lby);
        rates.sort(Comparator.comparingDouble(ProjectUtilizationRateVo::getUtilizationRate).reversed());
        return success(rates);
    }

    /**
     * 瑞都 设备利用率 按 项目部 统计
     * @return
     */
    @GetMapping("/rd/device/utilizationRates")
    @PermitAll
    public CommonResult<List<ProjectUtilizationRateVo>> rdUtilizationRates(IotRdDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 各项目部的设备利用率集合
        List<ProjectUtilizationRateVo> rates = new ArrayList<>();
        // 查询瑞都 163l 所有项目部
        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(163l);
        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key队伍id   value项目部id
        Map<Long, Long> teamIdProjectIdPair = new HashMap<>();
        // key项目部id   value A+B类设备id集合
        Map<Long, Set<Long>> projectABDeviceIdPair = new HashMap<>();
        // key项目部id   value 日报中A+B类设备id集合
        Map<Long, Set<Long>> projectReportABDeviceIdPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // 设备ID到其所属部门ID的映射
        Map<Long, Long> deviceIdToDeptIdMap = new HashMap<>();
        // key项目部id     value项目部下包含的队伍的 压裂 连油 设备数量
        Map<Long, Integer> projectDevicePair = new HashMap<>();
        // 瑞都 A B 类设备id 集合
        Set<Long> abDeviceCategoryIds = new HashSet<>();
        // 查询所有瑞都产品类别包含 A B 类
        IotProductClassifyListReqVO deviceCategoryReqVO = new IotProductClassifyListReqVO();
        List<IotProductClassifyDO> allDeviceCategories = iotProductClassifyMapper.selectList(deviceCategoryReqVO);
        if (CollUtil.isNotEmpty(allDeviceCategories)) {
            allDeviceCategories.forEach(category -> {
                if ("A".equals(category.getRemark())) {
                    abDeviceCategoryIds.add(category.getId());
                }
            });
        }
        // 查询 瑞都 施工状态 字典数据 筛选出施工设备为 LY 的记录
        Set<String> lyStatuses = new HashSet<>();
        List<DictDataDO> rdStatuses = dictDataService.getDictDataListByDictType("rdStatus");
        if (CollUtil.isNotEmpty(rdStatuses)) {
            rdStatuses.forEach(tech -> {
                if ("LY".equals(tech.getRemark())) {
                    lyStatuses.add(tech.getValue());
                }
            });
        }
        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if ("2".equals(dept.getType())) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId())) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                    // 设置每个队伍与上级项目部对应关系
                    teamIdProjectIdPair.put(dept.getId(), dept.getParentId());
                }
            });
            // 查询瑞都所有设备
            IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
            deviceReqVO.setDeptIds(new ArrayList<>(childDeptIds));
            List<IotDeviceDO> rdDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
            // 筛选每个项目部 A B 类设备id集合
            if (CollUtil.isNotEmpty(rdDevices)) {
                rdDevices.forEach(device -> {
                    Long projectId = 0l;
                    if (teamIdProjectIdPair.containsKey(device.getDeptId())) {
                        projectId = teamIdProjectIdPair.get(device.getDeptId());
                    }
                    if (projectDeptIds.contains(device.getDeptId())) {
                        projectId = device.getDeptId();
                    }
                    if (abDeviceCategoryIds.contains(device.getAssetClass())) {
                        if (projectABDeviceIdPair.containsKey(projectId)) {
                            Set<Long> tempDeviceIds = projectABDeviceIdPair.get(projectId);
                            tempDeviceIds.add(device.getId());
                            projectABDeviceIdPair.put(projectId, tempDeviceIds);
                        } else {
                            Set<Long> tempDeviceIds = new HashSet<>();
                            tempDeviceIds.add(device.getId());
                            projectABDeviceIdPair.put(projectId, tempDeviceIds);
                        }
                    }
                });
            }
        }
        // 查询出指定时间区间内 已经填写的日报 再根据设备id 进行筛选 通过设备id 建立项目部 与 日报数量之间的关联
        // 判断日报中 device_ids 字段中每个设备 是否属于需要统计的 压裂 连油 设备
        List<IotRdDailyReportDO> dailyReports = iotRdDailyReportMapper.dailyReports(reqVO);
        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
        Map<Long, Integer> projectReportPair = new HashMap<>();
        if (CollUtil.isNotEmpty(dailyReports)) {
            // 整理出每个项目部下的队伍填报的日报数量
            dailyReports.forEach(report -> {
                // 筛选出 可以统计 设备利用率的 日报状态 动迁 施工 施工准备
                // 区分不同项目部的日报
                if (lyStatuses.contains(report.getRdStatus())) {
                    Set<Long> reportDeviceIds = report.getDeviceIds();
                    // 获得当前日报施工队伍的上级项目部
                    if (teamIdProjectIdPair.containsKey(report.getDeptId())) {
                        Long projectId = teamIdProjectIdPair.get(report.getDeptId());
                        if (projectABDeviceIdPair.containsKey(projectId)) {
                            // 项目部下所有的AB类设备id集合
                            Set<Long> tempReportDeviceIds = projectABDeviceIdPair.get(projectId);
                            Set<Long> crossDeviceIds = CollUtil.isNotEmpty(reportDeviceIds)
                                    && CollUtil.isNotEmpty(tempReportDeviceIds)
                                    ? reportDeviceIds.stream() // 流式处理reportDeviceIds
                                    .filter(tempReportDeviceIds::contains) // 筛选出在tempReportDeviceIds中存在的元素
                                    .collect(Collectors.toSet()) // 收集为新的Set集合
                                    : Collections.emptySet(); // 任意集合为空则返回空Set（避免返回null）
                            if (projectReportABDeviceIdPair.containsKey(projectId)) {
                                Set<Long> tempDeviceIds = projectReportABDeviceIdPair.get(projectId);
                                tempDeviceIds.addAll(crossDeviceIds);
                                projectReportABDeviceIdPair.put(projectId, tempDeviceIds);
                            } else {
                                Set<Long> tempDeviceIds = new HashSet<>();
                                tempDeviceIds.addAll(crossDeviceIds);
                                projectReportABDeviceIdPair.put(projectId, tempDeviceIds);
                            }
                        }
                    }
                }
            });

            // 计算每个项目部的设备利用率 施工的设备数量/设备总数量
            if (CollUtil.isNotEmpty(projectABDeviceIdPair)) {

                projectABDeviceIdPair.forEach((projectDeptId, deviceIds) -> {
                    // 项目部下所有AB类设备
                    Integer projectDeviceCount = deviceIds.size();
                    // 项目部日报中施工的AB类设备
                    Integer reportDeviceCount = 0;
                    if (projectReportABDeviceIdPair.containsKey(projectDeptId)) {
                        Set<Long> reportDeviceIds = projectReportABDeviceIdPair.get(projectDeptId);
                        reportDeviceCount = reportDeviceIds.size();
                    }
                    ProjectUtilizationRateVo rateVo = new ProjectUtilizationRateVo();
                    rateVo.setProjectDeptId(projectDeptId);
                    if (projectPair.containsKey(projectDeptId)) {
                        rateVo.setProjectDeptName(projectPair.get(projectDeptId));
                    }
                    double rate = 0.0;
                    // 计算设备利用率（处理除数为0的情况）
                    if (projectDeviceCount > 0 && reportDeviceCount > 0) {
                        rate = new BigDecimal((double) reportDeviceCount / (projectDeviceCount))
                                .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数，四舍五入
                                .doubleValue();;
                    } else {
                        rate = 0;
                    }
                    rateVo.setUtilizationRate(rate); // 存储计算结果
                    rates.add(rateVo);
                });
            }
        }
        // 将返回列表中的 部门名称 去除多语言标识
        // 处理projectDeptName，截取~~首次出现前的字符串
        if (CollUtil.isNotEmpty(rates)) {
            rates.forEach(rateVo -> {
                String originalName = rateVo.getProjectDeptName();
                if (StrUtil.isNotBlank(originalName) && originalName.contains("~~")) {
                    // 截取首次~~之前的部分
                    String processedName = originalName.substring(0, originalName.indexOf("~~"));
                    rateVo.setProjectDeptName(processedName);
                }
                // 空值或无~~标识时，保留原名称
            });
        }
        rates.sort(Comparator.comparingDouble(ProjectUtilizationRateVo::getUtilizationRate).reversed());
        return success(rates);
    }

    /**
     * 瑞都 设备利用率 按 队伍 统计
     * @return
     */
    @GetMapping("/rd/device/teamUtilizationRate")
    @PermitAll
    public CommonResult<List<TeamUtilizationRateVo>> rdTeamUtilizationRate(IotRdDailyReportPageReqVO reqVO) {
        if (ObjUtil.isEmpty(reqVO.getCreateTime())) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        if (reqVO.getCreateTime().length < 2) {
            throw exception(IOT_DAILY_REPORT_TIME_NOT_EXISTS);
        }
        // 必须传递 项目部id 查询队伍数据
        if (ObjUtil.isEmpty(reqVO.getDeptId())) {
            throw exception(IOT_DAILY_REPORT_DEPT_NOT_EXISTS);
        }

        // 指定项目部的各队伍设备利用率集合
        List<TeamUtilizationRateVo> rates = new ArrayList<>();

        // 查询指定项目部下的 队伍集合
        DeptListReqVO deptReqVO = new DeptListReqVO();
        deptReqVO.setDeptId(reqVO.getDeptId());
        List<DeptDO> projectTeams = deptService.getDeptListByParentId(deptReqVO);
        // 指定项目部下的 队伍id集合
        Set<Long> projectTeamIds = new HashSet<>();
        if (CollUtil.isNotEmpty(projectTeams)) {
            projectTeams.forEach(team -> {
                projectTeamIds.add(team.getId());
            });
        }

        Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(projectTeamIds);

        Set<String> projectDeptNames = new HashSet<>();
        Set<Long> projectDeptIds = new HashSet<>();
        // key项目部id   value项目部名称
        Map<Long, String> projectPair = new HashMap<>();
        // key队伍id   value队伍名称
        Map<Long, String> teamPair = new HashMap<>();
        // key项目部id   value项目部包含的队伍id集合
        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
        // key队伍id   value队伍日报数量
        Map<Long, Long> teamReportCountPair = new HashMap<>();
        // key项目部id     value项目部下包含的队伍的 压裂 连油 设备数量
        Map<Long, Integer> projectDevicePair = new HashMap<>();
        // 设备ID到其所属部门ID的映射
        Map<Long, Long> deviceIdToDeptIdMap = new HashMap<>();

        if (CollUtil.isNotEmpty(allDeptPair)) {
            allDeptPair.forEach((deptId, dept) -> {
                if (dept.getName().contains("项目部") ) {
                    projectDeptIds.add(deptId);
                    projectDeptNames.add(dept.getName());
                    projectPair.put(deptId, dept.getName());
                }
                teamPair.put(deptId, dept.getName());
            });
            // 遍历所有部门
            allDeptPair.forEach((deptId, dept) -> {
                // 找出每个项目部下的队伍
                if (projectPair.containsKey(dept.getParentId())) {
                    // 获得当前部门的上级项目部
                    projectPair.forEach((projectDeptId, projectDept) -> {
                        if (projectDeptId.equals(dept.getParentId())) {
                            if (projectTeamPair.containsKey(projectDeptId)) {
                                Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            } else {
                                Set<Long> teamIds = new HashSet<>();
                                teamIds.add(deptId);
                                projectTeamPair.put(projectDeptId, teamIds);
                            }
                        }
                    });
                }
            });
        }
        if (CollUtil.isNotEmpty(projectTeamIds)) {
            // 查询不同项目部下 包含的 压裂泵车26 连油主车设备31
            // 查询 连油主车 或 压裂泵车 相应的设备类别 id集合
            Set<Long> utilizeDeviceCategoryIds = new HashSet<>();
            IotProductClassifyListReqVO categoryReqVO = new IotProductClassifyListReqVO();
            categoryReqVO.setName("连油主车");
            List<IotProductClassifyDO> deviceCategories = iotProductClassifyMapper.selectList(categoryReqVO);
            if (CollUtil.isNotEmpty(deviceCategories)) {
                utilizeDeviceCategoryIds.add(deviceCategories.get(0).getId());
            }
            // 查询 压裂泵车 的设备类别
            categoryReqVO.setName("压裂泵车");
            List<IotProductClassifyDO> pumpCategories = iotProductClassifyMapper.selectList(categoryReqVO);
            if (CollUtil.isNotEmpty(pumpCategories)) {
                pumpCategories.forEach(category -> {
                    utilizeDeviceCategoryIds.add(category.getId());
                });
            }
            IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
            deviceReqVO.setAssetClasses(new ArrayList<>(utilizeDeviceCategoryIds));
            List<IotDeviceDO> utilizeDevices = iotDeviceMapper.selectListAlone(deviceReqVO);

            if (CollUtil.isNotEmpty(utilizeDevices)) {
                utilizeDevices.forEach(device -> {
                    // 存储设备ID与所属部门ID的映射
                    deviceIdToDeptIdMap.put(device.getId(), device.getDeptId());
                    // 筛选出各队伍下的 压裂 连油 设备
                    projectTeamIds.forEach(teamId -> {
                        if (projectTeamIds.contains(device.getDeptId())) {
                            if (projectDevicePair.containsKey(teamId)) {
                                Integer tempCount = projectDevicePair.get(teamId);
                                projectDevicePair.put(teamId, ++tempCount);
                            } else {
                                projectDevicePair.put(teamId, 1);
                            }
                        }
                    });
                });
            }
            // 查询出指定时间区间内 已经填写的日报 再根据设备id 进行筛选 通过设备id 建立队伍 与 日报数量之间的关联
            // 判断日报中 device_ids 字段中每个设备 是否属于需要统计的 压裂 连油 设备
            List<IotRdDailyReportDO> dailyReports = iotRdDailyReportMapper.dailyReports(reqVO);
            // 筛选出每个队伍的日报
            if (CollUtil.isNotEmpty(dailyReports)) {
                // 设置每个队伍 相关 压裂 连油 设备 的日报数量
                dailyReports.forEach(report -> {
                    projectTeamIds.forEach(teamId -> {
                        Set<Long> tempDeviceIds = report.getDeviceIds();
                        // 判断 集合 tempDeviceIds 中的任意的 ‘设备id’ 是否包含在 集合 teamDeptIds 中
                        // 判断tempDeviceIds中的任意设备所属部门是否在当前项目部的队伍部门中
                        boolean hasMatchingDevice = CollUtil.isNotEmpty(tempDeviceIds) && tempDeviceIds.stream()
                                .map(deviceIdToDeptIdMap::get) // 通过映射表获取设备所属部门ID
                                .filter(Objects::nonNull) // 过滤掉非统计范围内的设备（避免空指针）
                                .anyMatch(teamId::equals); // 任意设备所属部门在队伍部门中则匹配
                        if (hasMatchingDevice) {
                            if (teamReportCountPair.containsKey(teamId)) {
                                Long tempCount = teamReportCountPair.get(teamId);
                                teamReportCountPair.put(teamId, ++tempCount);
                            } else {
                                teamReportCountPair.put(teamId, 1l);
                            }
                        }
                    });
                });

                // 计算指定时间区间内包含的天数
                long daysCount;
                if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                    LocalDateTime start = reqVO.getCreateTime()[0];
                    LocalDateTime end = reqVO.getCreateTime()[1];
                    if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
                        // 使用ChronoUnit.DAYS.between计算天数差，并+1包含首尾两天
                        daysCount = ChronoUnit.DAYS.between(
                                start.toLocalDate(),
                                end.toLocalDate()
                        ) + 1;
                    } else {
                        daysCount = 0L;
                    }
                } else {
                    daysCount = 0L;
                }
                // 计算每个队伍的设备利用率
                if (CollUtil.isNotEmpty(projectTeamIds)) {
                    projectTeamIds.forEach(teamId -> {
                        TeamUtilizationRateVo rateVo = new TeamUtilizationRateVo();
                        rateVo.setProjectDeptId(reqVO.getDeptId());
                        rateVo.setTeamId(teamId);
                        rateVo.setCumulativeDays(daysCount);
                        if (teamPair.containsKey(teamId)) {
                            rateVo.setTeamName(teamPair.get(teamId));
                        }
                        // 匹配出当前小队 日报数量
                        Long reportCount = 0l;
                        if (teamReportCountPair.containsKey(teamId)) {
                            reportCount = teamReportCountPair.getOrDefault(teamId, 0l);
                            rateVo.setConstructionDays(reportCount);
                        }
                        // 当前小队 设备利用率 公式 reportCount/daysCount
                        // 计算设备利用率（处理除数为0的情况）
                        double rate = 0.0;
                        if (reportCount > 0 && daysCount > 0) {
                            rate = new BigDecimal((double) reportCount /  daysCount)
                                    .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数，四舍五入
                                    .doubleValue();;
                        }
                        rateVo.setUtilizationRate(rate); // 存储计算结果
                        rates.add(rateVo);
                    });
                }
            }
        }
        // 将返回列表中的 部门名称 去除多语言标识
        // 处理projectDeptName，截取~~首次出现前的字符串
        if (CollUtil.isNotEmpty(rates)) {
            rates.forEach(rateVo -> {
                String originalName = rateVo.getTeamName();
                if (StrUtil.isNotBlank(originalName) && originalName.contains("~~")) {
                    // 截取首次~~之前的部分
                    String processedName = originalName.substring(0, originalName.indexOf("~~"));
                    rateVo.setTeamName(processedName);
                }
                // 空值或无~~标识时，保留原名称
            });
        }
        rates.sort(Comparator.comparingDouble(TeamUtilizationRateVo::getUtilizationRate).reversed());
        return success(rates);
    }

}

