package com.tofly.gpsboot.service.statement.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tofly.api.DepartmentClient;
import com.tofly.api.UserClent;
import com.tofly.common.oauth.util.SecurityUtils;
import com.tofly.es.PdaDeviceUpload;
import com.tofly.es.dto.EsQueryDto;
import com.tofly.gpsboot.common.Constant;
import com.tofly.gpsboot.common.business.DateTypeEnum;
import com.tofly.gpsboot.common.system.*;
import com.tofly.gpsboot.mapper.plan.PlanMapper;
import com.tofly.gpsboot.service.es.IPdaDeviceService;
import com.tofly.gpsboot.service.paln.PlanchildtypeService;
import com.tofly.gpsboot.service.paln.PlantypeService;
import com.tofly.pojo.statement.StatementAssess;
import com.tofly.pojo.statement.dto.StatementDto;
import com.tofly.pojo.statement.vo.*;
import com.tofly.pojo.trouble.vo.TroubleVo;
import com.tofly.gpsboot.mapper.trouble.TroubleMapper;
import com.tofly.gpsboot.service.config.InspectgroupService;
import com.tofly.gpsboot.service.maintain.*;
import com.tofly.gpsboot.service.paln.GpscalculateService;
import com.tofly.gpsboot.service.paln.GroupuserService;
import com.tofly.gpsboot.service.paln.task.PlanService;
import com.tofly.gpsboot.service.paln.task.PlanchildService;
import com.tofly.gpsboot.service.statement.IStatementService;
import com.tofly.gpsboot.service.trouble.ToubleplanService;
import com.tofly.gpsboot.service.trouble.ToubletypeService;
import com.tofly.gpsboot.service.trouble.TroubleService;
import com.tofly.gpsboot.util.DateTimeUtil;
import com.tofly.pojo.User;
import com.tofly.pojo.maintain.*;
import com.tofly.pojo.plan.*;
import com.tofly.pojo.trouble.Toubleplan;
import com.tofly.pojo.trouble.Trouble;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 报表相关服务实现类
 *
 * @author BZ-DJJ
 */
@Service("statementService")
public class StatementServiceImpl implements IStatementService {

    @Autowired
    private RepairorderService repairorderService;

    @Autowired
    private RepairuserService repairuserService;

    @Autowired
    private RepairtypeService repairtypeService;

    @Autowired
    private UserClent userClent;

    @Autowired
    private PlanService planService;
    @Autowired
    private PlanchildService planchildService;

    @Autowired
    private TroubleService troubleService;


    @Autowired
    private DepartmentClient departmentClient;

    @Autowired
    private ToubleplanService toubleplanService;

    @Autowired
    private ToubletypeService toubletypeService;

    @Autowired
    private GroupuserService groupuserService;

    @Autowired
    private GpscalculateService gpscalculateService;

    @Autowired
    private TroubleMapper troubleMapper;

    @Autowired
    private InspectgroupService inspectgroupService;
    @Autowired
    private IPdaDeviceService iPdaDeviceService;
    @Autowired
    private PlantypeService plantypeService;
    @Autowired
    private PlanchildtypeService planchildtypeService;


    @Override
    public List<MaintenanceStatisticsVo> getMaintenanceStatistics(StatementDto dto) {
        Date startDate = dto.getStartDate();
        Date endDate = dto.getEndDate();
        String regionCodeList = dto.getRegionCodeList();
        String userId = dto.getUserId();
        String deptId = dto.getDeptId();
        // 获取用户列表
        Set<Long> deptUserIdList = this.getDeptUserIdList(deptId, userId);
        List<Long> list = null;
        // 是否对应片区且状态为已完成
        if (StringUtils.isEmpty(regionCodeList)) {
            list = repairuserService.list(new QueryWrapper<Repairuser>().lambda().in(Repairuser::getRespUser, deptUserIdList).ge(Repairuser::getCreateTime, startDate).le(Repairuser::getCreateTime, endDate).eq(Repairuser::getState, OrderStateEnum.ORDER_STATE_PROCESSING_COMPLETE.getCode())).stream().map(Repairuser::getRepairId).collect(Collectors.toList());
        } else {
            List<String> codeList = Arrays.stream(regionCodeList.split(Constant.CSV))
                    .collect(Collectors.toList());
            list = repairuserService.list(new QueryWrapper<Repairuser>().lambda().in(Repairuser::getRespUser, deptUserIdList).ge(Repairuser::getCreateTime, startDate).le(Repairuser::getCreateTime, endDate).eq(Repairuser::getState, OrderStateEnum.ORDER_STATE_PROCESSING_COMPLETE.getCode()).in(Repairuser::getRegionCode, codeList)).stream().map(Repairuser::getRepairId).collect(Collectors.toList());
        }
        if (list.size() > 0) {
            List<Repairorder> repairOrderList = repairorderService.list(new QueryWrapper<Repairorder>().lambda().in(Repairorder::getId, list));
            // 类型id - 月份+数量
            Map<Long, Map<String, Long>> longMapMap = repairOrderList.stream().collect(Collectors.groupingBy(Repairorder::getTypeId, Collectors.groupingBy(order -> String.valueOf(DateTimeUtil.fromLong2LocalDateTime(order.getOverTime().getTime()).getYear()) + "-" + DateTimeUtil.fromLong2LocalDateTime(order.getOverTime().getTime()).getMonthValue(), Collectors.counting())));
            Map<String, List<MaintenanceStatisticsDetailVo>> map = new HashMap<>(12);
            longMapMap.forEach((k, v) -> {
                Repairtype repairtype = repairtypeService.getById(k);
                String groupName = repairtype.getGroupName();
                String name = repairtype.getName();
                String unit = repairtype.getUnit();
                if (map.containsKey(groupName)) {
                    List<MaintenanceStatisticsDetailVo> detailVos = map.get(groupName);
                    MaintenanceStatisticsDetailVo vo = new MaintenanceStatisticsDetailVo();
                    vo.setUnit(unit);
                    vo.setTypeName(name);
                    vo.setMonthNumMap(v);
                    detailVos.add(vo);
                    map.put(groupName, detailVos);
                } else {
                    List<MaintenanceStatisticsDetailVo> voList = new ArrayList<>();
                    MaintenanceStatisticsDetailVo vo = new MaintenanceStatisticsDetailVo();
                    vo.setUnit(unit);
                    vo.setTypeName(name);
                    vo.setMonthNumMap(v);
                    voList.add(vo);
                    map.put(groupName, voList);
                }

            });
            return map.entrySet().stream().map(e -> new MaintenanceStatisticsVo(e.getKey(), e.getValue())).collect(Collectors.toList());

        } else {
            return new ArrayList<>();
        }


    }


    @Override
    public List<TroubleTypeAnalysisVo> getTroubleTypeAnalysis(StatementDto dto) {
        String deptId = dto.getDeptId();
        String userId = dto.getUserId();
        Date startDate = dto.getStartDate();
        Date endDate = dto.getEndDate();
        List<TroubleTypeAnalysisVo> voList = new ArrayList<>();
        // 计划表和隐患计划关联表
        Set<Long> toublePlanIdList = toubleplanService.list().stream().map(Toubleplan::getPlanId).collect(Collectors.toSet());
        if (toublePlanIdList.size() > 0) {
            Set<Long> meetPlanIdList = planService.list(new QueryWrapper<Plan>().lambda().in(Plan::getId, toublePlanIdList).ge(Plan::getPlanBegindate, startDate).le(Plan::getPlanEnddate, endDate)).stream().map(Plan::getId).collect(Collectors.toSet());
            // 获取用户列表
            Set<Long> troubleUserIdList = this.getDeptUserIdList(deptId, userId);
            Set<Long> collect = planchildService.list(new QueryWrapper<Planchild>().lambda().in(Planchild::getPlanId, meetPlanIdList).in(Planchild::getRespUser, troubleUserIdList)).stream().map(Planchild::getPlanId).collect(Collectors.toSet());
            Set<Long> intersectionTroubleIdList = new HashSet<>();
            toublePlanIdList.forEach(toublePlanId -> {
                if (collect.contains(toublePlanId)) {
                    intersectionTroubleIdList.add(toublePlanId);
                }
            });
            // 查询对应隐患计划
            List<Trouble> troubleList = troubleService.list(new QueryWrapper<Trouble>().lambda().in(Trouble::getId, intersectionTroubleIdList));
            Map<Long, Map<String, Long>> mapMap = troubleList.stream().collect(Collectors.groupingBy(Trouble::getTypeId, Collectors.groupingBy(Trouble::getLocation, Collectors.counting())));

            mapMap.forEach((k, v) -> {
                TroubleTypeAnalysisVo vo = new TroubleTypeAnalysisVo();
                vo.setTroubleTypeName(toubletypeService.getById(k).getName());
                // 总数量
                long sum = v.values().stream().mapToLong(Long::byteValue).sum();
                v.forEach((ck, cv) -> {
                    vo.setLocation(ck);
                    int intValue = cv.intValue();
                    vo.setNum(intValue);
                    vo.setProportion(BigDecimal.valueOf(intValue).divide(BigDecimal.valueOf(sum), BigDecimal.ROUND_HALF_UP));
                    voList.add(vo);
                });
            });
        }

        return voList;
    }

    @Override
    public List<TroubleCauseVo> getTroubleCause(StatementDto dto) {
        List<TroubleCauseVo> voList = new ArrayList<>();
        Date startDate = dto.getStartDate();
        Date endDate = dto.getEndDate();
        // 多个片区
        String regionCodeList = dto.getRegionCodeList();
        QueryWrapper<Trouble> dtoQueryWrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(regionCodeList)) {
            List<String> regionIdList = Arrays.stream(regionCodeList.split(Constant.CSV))
                    .collect(Collectors.toList());
            dtoQueryWrapper.in("REGION_ID", regionIdList);
        }
        dtoQueryWrapper.ge("CREATE_TIME", startDate);
        dtoQueryWrapper.le("CREATE_TIME", endDate);

        List<Trouble> troubleVoList = troubleService.list(dtoQueryWrapper);
        if (null != troubleVoList && troubleVoList.size() > 0) {
            // 根据隐患类型分组对应数量
            Map<String, Long> counting = troubleVoList.stream()
                    .collect(Collectors.groupingBy(Trouble::getTypeIdName, Collectors.counting()));
            // 总数量/总比例
            long sum = counting.values().stream().mapToLong(Long::longValue).sum();
            counting.forEach((k, v) -> {
                TroubleCauseVo vo = new TroubleCauseVo();
                vo.setTroubleType(k);
                vo.setTroubleNum(v);
                vo.setRate(BigDecimal.valueOf(v).divide(BigDecimal.valueOf(sum), 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)));
                voList.add(vo);
            });
        }


        return voList;
    }

    @Override
    public List<TroubleTrendAnalysisVo> getTroubleTrendAnalysis(StatementDto dto) {
        List<TroubleTrendAnalysisVo> voList = new ArrayList<>();
        // 片区列表/隐患原因/时间类型,0年,1月/起始范围/终止范围
        String regionCodeList = dto.getRegionCodeList();
        String toubleType = dto.getToubleType();
        String dateType = dto.getDateType();
        Date startDate = dto.getStartDate();
        Date endDate = dto.getEndDate();
        QueryWrapper<Trouble> dtoQueryWrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(regionCodeList)) {
            List<String> regionIdList = Arrays.stream(regionCodeList.split(Constant.CSV))
                    .collect(Collectors.toList());
            dtoQueryWrapper.in("REGION_ID", regionIdList);
        }
        if (!StringUtils.isEmpty(toubleType)) {
            List<String> toubleTypeList = Arrays.stream(toubleType.split(Constant.CSV))
                    .collect(Collectors.toList());
            dtoQueryWrapper.in("TYPE_ID", toubleTypeList);
        }
        dtoQueryWrapper.ge("CREATE_TIME", startDate);
        dtoQueryWrapper.le("CREATE_TIME", endDate);
        List<Trouble> troubleVoList = troubleService.list(dtoQueryWrapper);

        Map<String, List<Trouble>> listMap = new HashMap<>(12);
        if (Constant.YEAR.equals(dateType)) {
            // 按照年分组
            listMap = troubleVoList.stream().collect(Collectors.groupingBy(t -> DateTimeUtil.getLocalDateTime(DateTimeUtil.fromLong2LocalDateTime(t.getCreateTime().getTime()), DateTimeUtil.YEARS_FORMAT)));
        } else {
            // 按照月分组
            listMap = troubleVoList.stream().collect(Collectors.groupingBy(t -> DateTimeUtil.getLocalDateTime(DateTimeUtil.fromLong2LocalDateTime(t.getCreateTime().getTime()), DateTimeUtil.FULL_MONTH_FORMAT)));
        }

        listMap.forEach((k, v) -> {
            int totalNum = v.size();
            // 按照类型分组
            Map<String, List<Trouble>> stringListMap = v.stream().collect(Collectors.groupingBy(Trouble::getTypeIdName, Collectors.toList()));
            stringListMap.forEach((z, m) -> {
                TroubleTrendAnalysisVo vo = new TroubleTrendAnalysisVo();
                vo.setAnalysisDate(k);
                vo.setTroubleTypeName(z);
                int size = m.size();
                vo.setNum((long) size);
                vo.setRate(BigDecimal.valueOf(size).divide(BigDecimal.valueOf(totalNum), 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)));
                voList.add(vo);
            });

        });
        return voList;
    }

    @Override
    public Page<TroubleRecordLedgerVo> getTroubleRecordLedger(Page page, StatementDto dto) {
        // 查询条件分组 人员 片区 状态 日期范围
        Set<Long> groupUserIdList = this.getGroupUserIdList(dto.getDeptId(), dto.getGroupId(), dto.getUserId());
        String regionCodeList = dto.getRegionCodeList();
        String troubleState = dto.getTroubleState();
        Date startDate = dto.getStartDate();
        Date endDate = dto.getEndDate();
        QueryWrapper<StatementDto> dtoQueryWrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(regionCodeList)) {
            List<String> regionIdList = Arrays.stream(regionCodeList.split(Constant.CSV))
                    .collect(Collectors.toList());
            dtoQueryWrapper.in("p.REGION_ID", regionIdList);
        }
        if (!StringUtils.isEmpty(troubleState)) {
            List<Long> troubleStateList = Arrays.stream(troubleState.split(Constant.CSV)).map(s -> Long.parseLong(s.trim()))
                    .collect(Collectors.toList());
            dtoQueryWrapper.in("p.STATE", troubleStateList);
        }
        dtoQueryWrapper.ge("p.CREATE_TIME", startDate);
        dtoQueryWrapper.le("p.CREATE_TIME", endDate);
        if (null != groupUserIdList && groupUserIdList.size() > 0) {
            dtoQueryWrapper.in("p.CREATE_USER", groupUserIdList);
        }

        Page infoPageList = troubleMapper.searchWeeklyPage(page, dtoQueryWrapper);
        // 转换前端显示对象
        infoPageList.setRecords(troubleRecordLedgerViewConversion(infoPageList.getRecords()));
        return infoPageList;
    }

    @Override
    public List<InspectionDayVo> getInspectionDay(StatementDto dto) {
        Date startDate = dto.getStartDate();
        Date endDate = dto.getEndDate();
        List<InspectionDayVo> voList = new ArrayList<>();
        // 获取查询的用户列表
        Set<Long> groupUserIdList = this.getGroupUserIdList(dto.getDeptId(), dto.getGroupId(), dto.getUserId());
        if (null != groupUserIdList && groupUserIdList.size() > 0) {
            // 获取当前统计的数据 当前用户列表下/对应时间范围
            List<Gpscalculate> gpsCalulateList = gpscalculateService.list(new QueryWrapper<Gpscalculate>().lambda().in(Gpscalculate::getUserId, groupUserIdList).ge(Gpscalculate::getGpsDate, startDate).lt(Gpscalculate::getGpsDate, endDate));
            // 按天查询
            long aLong = DateTimeUtil.differDays(DateTimeUtil.fromLong2LocalDateTime(startDate.getTime()), DateTimeUtil.fromLong2LocalDateTime(endDate.getTime()));
            Map<String, Map<Long, List<WorkCompletionVo>>> mapMap = new HashMap<>(12);
            for (int i = 0; i <= aLong; i++) {

                LocalDateTime beginTime = DateTimeUtil.getAssignTodayBeginTime(DateTimeUtil.fromLong2LocalDateTime(startDate.getTime()));
                LocalDateTime localDateTime = beginTime.plusDays(i);
                Date startTime = DateTimeUtil.convertLDTToDate(localDateTime);
                Date endTime = DateTimeUtil.convertLDTToDate(localDateTime.plusDays(i + 1));
                Map<Long, List<WorkCompletionVo>> workCompletion = this.getWorkCompletion(groupUserIdList, startTime, endTime);
                mapMap.put(DateTimeUtil.getLocalDateTime(localDateTime, DateTimeUtil.FULL_FORMAT), workCompletion);
            }


            gpsCalulateList.forEach(info -> {
                InspectionDayVo vo = new InspectionDayVo();
                vo.setDeptName(info.getDeptName());
                vo.setUserName(info.getUserName());
                vo.setInspectionDate(info.getGpsDate());
                vo.setPlanTotalDistance(BigDecimal.valueOf(info.getPlanTotalDistance()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                vo.setVaildTotalDistance(info.getVaildTotalDistance());
                vo.setFindTroubleNum(info.getFindTroubleNum());
                vo.setBuildingsitefinded(info.getBuildingsitefinded());
                vo.setPlanNum(info.getPlanNum());
                if (mapMap.size() > 0) {
                    String localDateTime = DateTimeUtil.getLocalDateTime(DateTimeUtil.fromLong2LocalDateTime(info.getGpsDate().getTime()), DateTimeUtil.FULL_FORMAT);
                    if (mapMap.containsKey(localDateTime)) {
                        vo.setWorkCompletionVoList(mapMap.get(localDateTime).get(info.getUserId()));
                    }

                }

                voList.add(vo);
            });


            voList.sort(Comparator.comparing(InspectionDayVo::getInspectionDate).reversed());
        }

        return voList;

    }


    @Override
    public List<InspectionMonthVo> getInspectionMonth(StatementDto dto) {
        List<InspectionMonthVo> voList = new ArrayList<>();
        Date startDate = dto.getStartDate();
        Date endDate = dto.getEndDate();
        // 获取查询的用户列表
        Set<Long> groupUserIdList = this.getGroupUserIdList(dto.getDeptId(), dto.getGroupId(), dto.getUserId());
        if (null != groupUserIdList && groupUserIdList.size() > 0) {
            // 按照月份分组
            Map<String, List<Gpscalculate>> monthDataMap = gpscalculateService.list(new QueryWrapper<Gpscalculate>().lambda().in(Gpscalculate::getUserId, groupUserIdList).ge(Gpscalculate::getGpsDate, startDate).lt(Gpscalculate::getGpsDate, endDate)).stream().collect(Collectors.groupingBy(g -> DateTimeUtil.getLocalDateTime(DateTimeUtil.fromLong2LocalDateTime(g.getGpsDate().getTime()), DateTimeUtil.FULL_MONTH_FORMAT), Collectors.toList()));
            monthDataMap.forEach((k, v) -> {
                // 分组用户
                Map<Long, List<Gpscalculate>> listMap = v.stream().collect(Collectors.groupingBy(Gpscalculate::getUserId, Collectors.toList()));
                // key->用户id key->用户名称
                Map<Long, String> userIdNameMap = v.stream().
                        collect(Collectors.
                                toMap(Gpscalculate::getUserId, Gpscalculate::getUserName, (item1, item2) -> item1));
                Map<Long, String> deptNameMap = v.stream().
                        collect(Collectors.
                                toMap(Gpscalculate::getUserId, Gpscalculate::getDeptName, (item1, item2) -> item1));
                Date gpsDate = v.stream().min(Comparator.comparing(Gpscalculate::getGpsDate)).get().getGpsDate();
                LocalDateTime localDateTime = DateTimeUtil.fromLong2LocalDateTime(gpsDate.getTime());
                LocalDate startMonth = DateTimeUtil.getFirstDayOfCurrentSpecifiedMonth(localDateTime);
                LocalDate endMonth = DateTimeUtil.getLastDayOfCurrentSpecifiedMonth(localDateTime);
                Date startTime = DateTimeUtil.localDateToDate(startMonth);
                Date endTime = DateTimeUtil.localDateToDate(endMonth);
                Map<Long, List<WorkCompletionVo>> workCompletion = this.getWorkCompletion(groupUserIdList, startTime, endTime);

                listMap.forEach((z, x) -> {
                    InspectionMonthVo vo = new InspectionMonthVo();
                    vo.setMonth(k);
                    vo.setDeptName(deptNameMap.get(z));
                    vo.setUserName(userIdNameMap.get(z));
                    vo.setInspectionDateMonth(DateTimeUtil.getLocalDateTime(DateTimeUtil.fromLong2LocalDateTime(startTime.getTime()), DateTimeUtil.DAY_FORMAT) + " ~ " + DateTimeUtil.getLocalDateTime(DateTimeUtil.fromLong2LocalDateTime(endTime.getTime()), DateTimeUtil.DAY_FORMAT));
                    vo.setFindTroubleNum(x.stream().mapToLong(Gpscalculate::getFindTroubleNum).sum());
                    vo.setBuildingsitefinded(x.stream().mapToLong(Gpscalculate::getBuildingsitefinded).sum());
                    vo.setPlanTotalDistance(BigDecimal.valueOf(x.stream().mapToDouble(Gpscalculate::getPlanTotalDistance).sum()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                    vo.setVaildSpeed(x.stream().mapToDouble(Gpscalculate::getVaildSpeed).sum());
                    vo.setPlanNum(x.stream().max(Comparator.comparing(Gpscalculate::getGpsDate)).get().getPlanNum());
                    vo.setWorkCompletionVoList(workCompletion.get(z));

                    voList.add(vo);
                });

            });
            voList.sort(Comparator.comparing(InspectionMonthVo::getMonth).reversed());
        }

        return voList;
    }

    @Override
    public List<InspectionStatisticsVo> getInspectionStatistics(StatementDto dto) {
        List<InspectionStatisticsVo> voList = new ArrayList<>();
        Date startDate = dto.getStartDate();
        Date endDate = dto.getEndDate();
        // 获取查询的用户列表
        Set<Long> groupUserIdList = this.getGroupUserIdList(dto.getDeptId(), dto.getGroupId(), dto.getUserId());
        if (null != groupUserIdList && groupUserIdList.size() > 0) {
            List<Gpscalculate> gpscalculateList = gpscalculateService.list(new QueryWrapper<Gpscalculate>().lambda().in(Gpscalculate::getUserId, groupUserIdList).ge(Gpscalculate::getGpsDate, startDate).lt(Gpscalculate::getGpsDate, endDate));
            // 按照用户分组
            Map<Long, List<Gpscalculate>> listMap = gpscalculateList.stream().collect(Collectors.groupingBy(Gpscalculate::getUserId, Collectors.toList()));
            // key->用户id key->用户名称
            Map<Long, String> userIdNameMap = gpscalculateList.stream().
                    collect(Collectors.
                            toMap(Gpscalculate::getUserId, Gpscalculate::getUserName, (item1, item2) -> item1));
            Map<Long, String> deptNameMap = gpscalculateList.stream().
                    collect(Collectors.
                            toMap(Gpscalculate::getUserId, Gpscalculate::getDeptName, (item1, item2) -> item1));
            Map<Long, List<WorkCompletionVo>> workCompletion = this.getWorkCompletion(groupUserIdList, startDate, endDate);
            listMap.forEach((k, v) -> {
                InspectionStatisticsVo vo = new InspectionStatisticsVo();
                List<Groupuser> list = groupuserService.list(new QueryWrapper<Groupuser>().lambda().eq(Groupuser::getUserId, k));
                if (null != list && list.size() > 0) {
                    String groupId = list.get(0).getGroupId();
                    Inspectgroup byId = inspectgroupService.getById(groupId);
                    if (null != byId) {
                        vo.setGroupName(byId.getName());
                    }

                }

                vo.setUserName(userIdNameMap.get(k));
                vo.setDeptName(deptNameMap.get(k));
                vo.setFindTroubleNum(v.stream().mapToLong(Gpscalculate::getFindTroubleNum).sum());
                vo.setBuildingsitefinded(v.stream().mapToLong(Gpscalculate::getBuildingsitefinded).sum());
                vo.setPlanTotalDistance(BigDecimal.valueOf(v.stream().mapToDouble(Gpscalculate::getPlanTotalDistance).sum()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                vo.setVaildSpeed(v.stream().mapToDouble(Gpscalculate::getVaildSpeed).sum());
                vo.setPlanNum(v.stream().max(Comparator.comparing(Gpscalculate::getGpsDate)).get().getPlanNum());
                vo.setWorkCompletionVoList(workCompletion.get(k));

                voList.add(vo);
            });
        }

        return voList;
    }

    @Override
    public List<AttendanceRecordsVo> getAttendanceRecords(StatementDto dto) {
        List<AttendanceRecordsVo> voList = new ArrayList<>();
        Date startDate = dto.getStartDate();
        Date endDate = dto.getEndDate();
        // 获取查询的用户列表
        Set<Long> groupUserIdList = this.getGroupUserIdList(dto.getDeptId(), dto.getGroupId(), dto.getUserId());
        // 获取当前时间范围内的计划id列表
        if (null != groupUserIdList && groupUserIdList.size() > 0) {
            List<Gpscalculate> gpscalculateList = gpscalculateService.list(new QueryWrapper<Gpscalculate>().lambda().in(Gpscalculate::getUserId, groupUserIdList).ge(Gpscalculate::getGpsDate, startDate).le(Gpscalculate::getGpsDate, endDate));
            Map<Long, List<Gpscalculate>> collect = gpscalculateList.stream().collect(Collectors.groupingBy(Gpscalculate::getUserId));
            // key->用户id key->用户名称
            Map<Long, String> userIdNameMap = gpscalculateList.stream().
                    collect(Collectors.
                            toMap(Gpscalculate::getUserId, Gpscalculate::getUserName, (item1, item2) -> item1));
            Map<Long, String> deptNameMap = gpscalculateList.stream().
                    collect(Collectors.
                            toMap(Gpscalculate::getUserId, Gpscalculate::getDeptName, (item1, item2) -> item1));
            collect.forEach((k, v) -> {
                AttendanceRecordsVo vo = new AttendanceRecordsVo();
                List<Groupuser> list = groupuserService.list(new QueryWrapper<Groupuser>().lambda().eq(Groupuser::getUserId, k));
                if (null != list && list.size() > 0) {
                    String groupId = list.get(0).getGroupId();
                    Inspectgroup byId = inspectgroupService.getById(groupId);
                    if (null != byId) {
                        vo.setGroupName(byId.getName());
                    }

                }
                vo.setUserName(userIdNameMap.get(k));
                vo.setDeptName(deptNameMap.get(k));
                vo.setWorkHours(DateTimeUtil.getLocalDateTime(DateTimeUtil.fromLong2LocalDateTime(startDate.getTime()), DateTimeUtil.FULL_FORMAT) + " ~ " + DateTimeUtil.getLocalDateTime(DateTimeUtil.fromLong2LocalDateTime(endDate.getTime()), DateTimeUtil.FULL_FORMAT));
                vo.setFindTroubleNum(v.stream().mapToLong(Gpscalculate::getFindTroubleNum).sum());
                vo.setBuildingsitefinded(v.stream().mapToLong(Gpscalculate::getBuildingsitefinded).sum());
                vo.setPlanTotalDistance(v.stream().mapToDouble(Gpscalculate::getPlanTotalDistance).sum());
                vo.setVaildSpeed(v.stream().mapToDouble(Gpscalculate::getVaildSpeed).sum());
                vo.setPlanNum(v.stream().max(Comparator.comparing(Gpscalculate::getGpsDate)).get().getPlanNum());
                long pointpatroled = v.stream().mapToLong(Gpscalculate::getPointpatroled).sum();
                BigDecimal pathpatroled = v.stream().map(Gpscalculate::getPathpatroled).reduce(BigDecimal.ZERO, BigDecimal::add);
                long completeOrderNum = v.stream().mapToLong(Gpscalculate::getCompleteOrderNum).sum();
                long orderNum = v.stream().mapToLong(Gpscalculate::getRepairOrderNum).sum();
                // 获取统计时间最大的数据作为 最新数据

                Gpscalculate gpscalculate = v.stream().max(Comparator.comparing(Gpscalculate::getGpsDate)).get();
                vo.setInspectNode("" + "计划巡检点个数: " + gpscalculate.getPointinplan() + ",实际巡检点个数: " + pointpatroled + ",计划巡检线长度: " + gpscalculate.getPathinplan() + ",实际巡检线长度: " + pathpatroled);
                vo.setMaintainNode("" + "计划工单个数: " + orderNum + ",实际完成工单个数: " + completeOrderNum);
                voList.add(vo);
            });

            voList.sort(Comparator.comparing(AttendanceRecordsVo::getWorkHours).reversed());


        }

        return voList;
    }

    @Override
    public List<SchedulingVo> getScheduling(StatementDto dto) {
        List<SchedulingVo> voList = new ArrayList<>();
        Date startDate = dto.getStartDate();
        Date endDate = dto.getEndDate();
        // 获取查询的用户列表
        Set<Long> groupUserIdList = this.getGroupUserIdList(dto.getDeptId(), dto.getGroupId(), dto.getUserId());
        if (null != groupUserIdList && groupUserIdList.size() > 0) {
            // 根据用户列表 时间范围获取统计数据
            List<Gpscalculate> gpscalculateList = gpscalculateService.list(new QueryWrapper<Gpscalculate>().lambda().in(Gpscalculate::getUserId, groupUserIdList).ge(Gpscalculate::getGpsDate, startDate).le(Gpscalculate::getGpsDate, endDate));
            Map<Long, List<Gpscalculate>> collect = gpscalculateList.stream().collect(Collectors.groupingBy(Gpscalculate::getUserId));
            // key->用户id key->用户名称
            Map<Long, String> userIdNameMap = gpscalculateList.stream().
                    collect(Collectors.
                            toMap(Gpscalculate::getUserId, Gpscalculate::getUserName, (item1, item2) -> item1));

            collect.forEach((k, v) -> {
                SchedulingVo vo = new SchedulingVo();
                vo.setTime(DateTimeUtil.getLocalDateTime(DateTimeUtil.fromLong2LocalDateTime(startDate.getTime()), DateTimeUtil.FULL_FORMAT) + " ~ " + DateTimeUtil.getLocalDateTime(DateTimeUtil.fromLong2LocalDateTime(endDate.getTime()), DateTimeUtil.FULL_FORMAT));
                vo.setUserName(userIdNameMap.get(k));
                long findNum = v.stream().mapToLong(Gpscalculate::getFindTroubleNum).sum();
                long buNum = v.stream().mapToLong(Gpscalculate::getBuildingsitefinded).sum();
                Gpscalculate gpscalculate = v.stream().max(Comparator.comparing(Gpscalculate::getGpsDate)).get();
                vo.setNode("" + "计划巡检点个数: " + gpscalculate.getPointinplan() + ",计划巡检线长度: " + gpscalculate.getPathinplan() + ",隐患发现数: " + buNum + ",工地发现数: " + findNum);
                voList.add(vo);
            });
            voList.sort(Comparator.comparing(SchedulingVo::getTime).reversed());
        }

        return voList;
    }

    @Override
    public Page<List<PdaDeviceUpload>> getTerminalRecord(Page page, StatementDto dto, String exportFlag) {
        Date startDate = dto.getStartDate();
        Date endDate = dto.getEndDate();
        String userId = dto.getUserId();
        String deptId = dto.getDeptId();
        // 获取用户列表
        Set<Long> userIdList = this.getDeptUserIdList(deptId, userId);
        EsQueryDto esQueryDto = new EsQueryDto();
        esQueryDto.setStartDate(startDate);
        esQueryDto.setEndDate(endDate);
        esQueryDto.setIsExport(exportFlag);
        StringBuilder stringBuilder = new StringBuilder("");
        userIdList.forEach(info -> {
            stringBuilder.append(info).append(Constant.CSV);
        });
        if (stringBuilder.length() > 0) {
            esQueryDto.setUserIds(stringBuilder.deleteCharAt(stringBuilder.length() - 1).toString());
        }
        return iPdaDeviceService.getPageGpsInfo(page, esQueryDto);
    }

    @Override
    public List<InspectionStatisticsVo> getInspectionStatement(StatementDto dto) {
        String dateType = dto.getDateType();
        // 判断时间类型,(0年,1月,2季)
        List<InspectionStatisticsVo> voList = new ArrayList<>();
        Date startDate = dto.getStartDate();
        Date endDate = dto.getEndDate();
        // 获取查询的用户列表
        Set<Long> groupUserIdList = this.getGroupUserIdList(dto.getDeptId(), dto.getGroupId(), dto.getUserId());
        if (null != groupUserIdList && groupUserIdList.size() > 0) {
            Map<LocalDateTime, LocalDateTime> dateDateMap = new HashMap<>(12);
            // 将日期按照时间类型拆分
            LocalDateTime starTime = DateTimeUtil.fromLong2LocalDateTime(startDate.getTime());
            LocalDateTime endTime = DateTimeUtil.fromLong2LocalDateTime(endDate.getTime());
            if (DateTypeEnum.YEAR.getCode().equals(dateType)) {
                LocalDateTime yearTime = LocalDateTime.of(DateTimeUtil.UDateToLocalDate(startDate).with(TemporalAdjusters.firstDayOfYear()), LocalTime.MIN);
                int starYear = starTime.getYear();
                int endYear = endTime.getYear();
                int y = endYear - starYear;
                for (int i = 0; i <= y; i++) {
                    LocalDateTime localDateTime = yearTime.plusYears(1);
                    dateDateMap.put(yearTime, localDateTime);
                    yearTime = localDateTime;
                }
            } else if (DateTypeEnum.MONTH.getCode().equals(dateType)) {
                LocalDateTime monthTime = LocalDateTime.of(DateTimeUtil.UDateToLocalDate(startDate).with(TemporalAdjusters.firstDayOfMonth()), LocalTime.MIN);
                int startMonth = starTime.getMonthValue();
                int endMonth = endTime.getMonthValue();
                int m = endMonth - startMonth;
                for (int i = 0; i <= m; i++) {
                    LocalDateTime localDateTime = monthTime.plusMonths(1);
                    dateDateMap.put(monthTime, localDateTime);
                    monthTime = localDateTime;
                }
            } else if (DateTypeEnum.QUARTER.getCode().equals(dateType)) {
                LocalDateTime quarterStartTime = DateTimeUtil.quarterStartTime(DateTimeUtil.UDateToLocalDate(startDate));
                int startMonth = starTime.getMonthValue();
                int endMonth = endTime.getMonthValue();
                int m = (endMonth - startMonth) / 3;
                for (int i = 0; i <= m; i++) {
                    LocalDateTime localDateTime = quarterStartTime.plusMonths(2);
                    dateDateMap.put(quarterStartTime, localDateTime);
                    quarterStartTime = localDateTime;
                }
            }

            dateDateMap.forEach((s, e) -> {
                Date starConvert = DateTimeUtil.convert(s);
                Date endconvert = DateTimeUtil.convert(e);
                List<Gpscalculate> gpscalculateList = gpscalculateService.list(new QueryWrapper<Gpscalculate>().lambda()
                        .in(Gpscalculate::getUserId, groupUserIdList)
                        .ge(Gpscalculate::getGpsDate, starConvert)
                        .lt(Gpscalculate::getGpsDate, endconvert));
                Map<String, List<Gpscalculate>> collect = new HashMap<>(12);
                if (DateTypeEnum.YEAR.getCode().equals(dateType)) {
                    collect = gpscalculateList.stream().collect(Collectors.groupingBy(g -> DateTimeUtil.getLocalDateTime(
                            DateTimeUtil.fromLong2LocalDateTime(g.getGpsDate().getTime()), DateTimeUtil.YEARS_FORMAT)));
                } else if (DateTypeEnum.QUARTER.getCode().equals(dateType)) {
                    collect = gpscalculateList.stream().collect(Collectors.groupingBy(g -> DateTimeUtil.quarterStartTimeInt(DateTimeUtil.UDateToLocalDate(g.getGpsDate()))));

                } else {
                    collect = gpscalculateList.stream().collect(Collectors.groupingBy(g -> DateTimeUtil.getLocalDateTime(
                            DateTimeUtil.fromLong2LocalDateTime(g.getGpsDate().getTime()), DateTimeUtil.FULL_MONTH_FORMAT)));
                }

                collect.forEach((k, v) -> {
                    // 分组用户
                    Map<Long, List<Gpscalculate>> listMap = v.stream().collect(Collectors.groupingBy(Gpscalculate::getUserId, Collectors.toList()));
                    // key->用户id key->用户名称
                    Map<Long, String> userIdNameMap = v.stream().
                            collect(Collectors.
                                    toMap(Gpscalculate::getUserId, Gpscalculate::getUserName, (item1, item2) -> item1));
                    Map<Long, String> deptNameMap = v.stream().
                            collect(Collectors.
                                    toMap(Gpscalculate::getUserId, Gpscalculate::getDeptName, (item1, item2) -> item1));
                    Map<Long, List<WorkCompletionVo>> workCompletion = this.getWorkCompletion(groupUserIdList, starConvert, endconvert);

                    listMap.forEach((z, x) -> {
                        InspectionStatisticsVo vo = new InspectionStatisticsVo();
                        vo.setStatisticDate(k);
                        vo.setDeptName(deptNameMap.get(k));
                        vo.setUserId(z);
                        vo.setUserName(userIdNameMap.get(z));
                        vo.setFindTroubleNum(x.stream().mapToLong(Gpscalculate::getFindTroubleNum).sum());
                        vo.setBuildingsitefinded(x.stream().mapToLong(Gpscalculate::getBuildingsitefinded).sum());
                        vo.setPlanTotalDistance(BigDecimal.valueOf(x.stream().mapToDouble(Gpscalculate::getPlanTotalDistance).sum()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                        vo.setVaildSpeed(x.stream().mapToDouble(Gpscalculate::getVaildSpeed).sum());
                        vo.setPlanNum(x.stream().max(Comparator.comparing(Gpscalculate::getGpsDate)).get().getPlanNum());
                        vo.setWorkCompletionVoList(workCompletion.get(z));

                        voList.add(vo);
                    });
                });

            });

            voList.sort(Comparator.comparing(InspectionStatisticsVo::getStatisticDate).reversed());
        }

        return voList;
    }
    /**
     * 获取任务执行情况map
     *
     * @param userIds
     * @param stateTime
     * @param endTime
     * @return
     */
    private Map<Long, List<WorkCompletionVo>> getWorkCompletion(Set<Long> userIds, Date stateTime, Date endTime) {
        // 数据封装
        Map<Long, List<WorkCompletionVo>> voMap = new HashMap<>(12);
        // 获取满足时间范围的主计划
        Set<Long> planIdMainList = planService.list(new QueryWrapper<Plan>().lambda()
                .ge(Plan::getPlanBegindate, stateTime).le(Plan::getPlanEnddate, endTime)
                .or().le(Plan::getPlanBegindate, stateTime).ge(Plan::getPlanEnddate, endTime)).stream().map(Plan::getId).collect(Collectors.toSet());

        if (planIdMainList.size() > 0) {
            // 获取对应用户下的子计划
            List<Planchild> planChildList = planchildService.list(new QueryWrapper<Planchild>().lambda().in(Planchild::getPlanId, planIdMainList).in(Planchild::getRespUser, userIds));
            if (null != planChildList && planChildList.size() > 0) {
                Map<Long, List<Planchild>> collect = planChildList.stream().collect(Collectors.groupingBy(Planchild::getRespUser));
                collect.forEach((e, r) -> {
                    // 获取子计划id列表
                    Set<Long> planChildIdList = r.stream().map(Planchild::getId).collect(Collectors.toSet());
                    Set<Long> planIdList = r.stream().map(Planchild::getPlanId).collect(Collectors.toSet());
                    // 主 类型分组
                    Map<String, List<Plantype>> typeMap = plantypeService.list(new QueryWrapper<Plantype>().lambda().in(Plantype::getPlanId, planIdList)).stream().filter(i -> null != i.getTypeName()).collect(Collectors.groupingBy(Plantype::getTypeName));
                    // 子 用户分组
                    Map<Long, List<Planchildtype>> longListMap = planchildtypeService.list(new QueryWrapper<Planchildtype>().lambda().in(Planchildtype::getPlanChildId, planChildIdList)).stream().collect(Collectors.groupingBy(Planchildtype::getUserId));
                    List<WorkCompletionVo> voList = new ArrayList<>();
                    typeMap.forEach((z, x) -> {
                        BigDecimal totalCount = x.stream().map(Plantype::getTotalCount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal totalLen = x.stream().map(Plantype::getTotalLength).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal overCount = x.stream().map(Plantype::getOverCount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal overLen = x.stream().map(Plantype::getOverLength).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal totalCountRate = overCount.divide(totalCount, 2, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
                        BigDecimal totalLenRate = BigDecimal.ZERO;
                        if (null != totalLen && !totalLen.equals(BigDecimal.ZERO)) {
                            totalLenRate = overLen.divide(totalLen, 2, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
                        }
                        BigDecimal finalTotalLenRate = totalLenRate;
                        WorkCompletionVo vo = new WorkCompletionVo();
                        vo.setTypeName(z);
                        StringBuilder builder = new StringBuilder("");
                        builder.append("总点数: ")
                                .append(totalCount)
                                .append(",总长度: ")
                                .append(totalLen)
                                .append(",总完成点个数: ")
                                .append(overCount)
                                .append(",总完成线长度: ")
                                .append(overLen)
                                .append(",总完成率: ")
                                .append(totalCountRate)
                                .append("%")
                                .append(",总线比例: ")
                                .append(finalTotalLenRate)
                                .append("%");
                        List<Planchildtype> planchildtypes = longListMap.get(e);
                        if (null != planchildtypes && planchildtypes.size() > 0) {
                            Map<String, List<Planchildtype>> planChildTypeMap = planchildtypes.stream().filter(i -> null != i.getTypeName()).collect(Collectors.groupingBy(Planchildtype::getTypeName));
                            List<Planchildtype> v = planChildTypeMap.get(z);
                            BigDecimal userCount = BigDecimal.ZERO;
                            BigDecimal userLen = BigDecimal.ZERO;
                            if (null != v) {
                                userCount = v.stream().map(Planchildtype::getOverCount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                                userLen = v.stream().map(Planchildtype::getOverLength).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                            }
                            BigDecimal lenRate = BigDecimal.ZERO;
                            if (null != totalLen && !totalLen.equals(BigDecimal.ZERO)) {
                                lenRate = userLen.divide(totalLen, 2, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
                            }
                            BigDecimal countRate = userCount.divide(totalCount, 2, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
                            builder.append(",个人完成点个数: ")
                                    .append(userCount)
                                    .append(",个人完成线长度: ")
                                    .append(userLen)
                                    .append(",个人完成率: ")
                                    .append(countRate)
                                    .append("%")
                                    .append(",个人线比例: ")
                                    .append(lenRate)
                                    .append("%");
                            vo.setStatisticalUserId(e);
                            vo.setLenRate(countRate);
                            vo.setPointRate(lenRate);
                        }
                        vo.setNode(builder.toString());
                        voList.add(vo);
                    });
                    voMap.put(e,voList);
                });


            }
        }


        return voMap;

    }


    private List<TroubleRecordLedgerVo> troubleRecordLedgerViewConversion(List<TroubleRecordLedgerVo> voList) {
        voList.forEach(info -> {
            // 转换隐患部位 隐患原因 是否进入工地 隐患是否消除 上报人名称
            info.setLocation(TroublePartEnum.getCodeForValue(info.getLocation()));
            String typeId = info.getTroubleTypeId();
            if (!StringUtils.isEmpty(typeId)) {
                info.setTroubleTypeName(toubletypeService.getById(typeId).getName());
            }
            info.setIsBuild(IsBuildEnum.getCodeForValue(info.getIsBuild()));
            info.setIsSuggest(IsBuildEnum.getCodeForValue(info.getIsSuggest()));
            Long submitUser = info.getSubmitUserid();
            if (null != submitUser && 0 != submitUser) {
                User userAudit = userClent.getById(submitUser).getResult();
                if (null != userAudit) {
                    info.setSubmitUserName(userAudit.getRealName());
                }

            }

        });
        return voList;
    }


    /**
     * 根据分组id,用户id (不传则默认当前部门下所有用户)获取查询用户id列表
     *
     * @param deptId
     * @param groupId
     * @param userId
     * @return
     */
    private Set<Long> getGroupUserIdList(String deptId, String groupId, String userId) {
        Set<Long> groupUserIdList = new HashSet<>();

        if (!StringUtils.isEmpty(deptId)) {
            groupUserIdList = departmentClient.getDeptUserList(Long.valueOf(deptId)).getResult().stream().map(User::getId).collect(Collectors.toSet());
        } else if (StringUtils.isEmpty(groupId)) {
            // 当前登录用户部门id
            Long departmentId = SecurityUtils.getUser().getDepartmentId();
            groupUserIdList = departmentClient.getDeptUserList(departmentId).getResult().stream().map(User::getId).collect(Collectors.toSet());
        }
        if (!StringUtils.isEmpty(groupId)) {
            groupUserIdList.clear();
            groupUserIdList = groupuserService.list(new QueryWrapper<Groupuser>().lambda().eq(Groupuser::getGroupId, groupId)).stream().map(g -> Long.valueOf(g.getUserId())).collect(Collectors.toSet());
        }
        if (!StringUtils.isEmpty(userId)) {
            groupUserIdList.clear();
            List<Long> ids = Arrays.stream(userId.split(Constant.CSV)).map(s -> Long.parseLong(s.trim()))
                    .collect(Collectors.toList());
            groupUserIdList.addAll(ids);
        }
        return groupUserIdList;
    }

    private Set<Long> getDeptUserIdList(String deptId, String userId) {
        Set<Long> deptUserIdList;
        if (!StringUtils.isEmpty(deptId)) {
            deptUserIdList = departmentClient.getDeptUserList(Long.valueOf(deptId)).getResult().stream().map(User::getId).collect(Collectors.toSet());
        } else {
            // 当前登录用户部门id
            Long departmentId = SecurityUtils.getUser().getDepartmentId();
            deptUserIdList = departmentClient.getDeptUserList(departmentId).getResult().stream().map(User::getId).collect(Collectors.toSet());
        }

        if (!StringUtils.isEmpty(userId)) {
            deptUserIdList.clear();
            List<Long> ids = Arrays.stream(userId.split(Constant.CSV)).map(s -> Long.parseLong(s.trim()))
                    .collect(Collectors.toList());
            deptUserIdList.addAll(ids);
        }
        return deptUserIdList;
    }

}
