package com.njcn.supervision.service.gridDiagram.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.param.StatisticsBizBaseParam;
import com.njcn.supervision.enums.FlowStatusEnum;
import com.njcn.supervision.mapper.device.TempLineRunTestWarningMapper;
import com.njcn.supervision.pojo.po.device.LineWarning;
import com.njcn.supervision.pojo.po.leaflet.WarningLeaflet;
import com.njcn.supervision.pojo.po.problem.SupervisionUserComplaintPO;
import com.njcn.supervision.pojo.po.survey.SurveyTest;
import com.njcn.supervision.pojo.vo.gridDiagram.GridDiagramVO;
import com.njcn.supervision.service.device.ILineWarningService;
import com.njcn.supervision.service.gridDiagram.GridDiagramService;
import com.njcn.supervision.service.leaflet.IWarningLeafletService;
import com.njcn.supervision.service.problem.SupervisionUserComplaintPOService;
import com.njcn.supervision.service.survey.ISurveyTestService;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.pojo.dto.DeptDTO;
import com.njcn.web.utils.WebUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author wr
 * @date 2024/6/13 14:53
 */
@Service
@RequiredArgsConstructor
public class GridDiagramServiceImpl implements GridDiagramService {

    private final SupervisionUserComplaintPOService userComplaintPOService;
    private final ISurveyTestService surveyTestService;
    private final DeptFeignClient deptFeignClient;
    private final IWarningLeafletService warningLeafletService;
    private final ILineWarningService lineWarningService;
    private final TempLineRunTestWarningMapper warningsMapper;

    @Override
    public GridDiagramVO.Info getSupervisionData(StatisticsBizBaseParam param) {
        List<String> deptIds = deptFeignClient.getDepSonIdtByDeptId(param.getId()).getData();
        return supervisionDetailsAdd(null, deptIds, param);
    }

    @Override
    public List<GridDiagramVO.Info> getSupervisionDetailsData(StatisticsBizBaseParam param) {
        List<GridDiagramVO.Info> info = new ArrayList<>();
        //获取包括当前部门的后代所有部门信息
        List<DeptDTO> deptInfos = deptFeignClient.getDeptDescendantIndexes(param.getId(), WebUtil.filterDeptType()).getData();
        List<DeptDTO> directDeptInfos = deptInfos.stream()
                .filter(deptDTO -> deptDTO.getPid().equals(param.getId()))
                .collect(Collectors.toList());
        if (CollectionUtil.isEmpty(directDeptInfos)) {
            //没有直接子部门，获取当前部门所有信息
            List<DeptDTO> dept = deptInfos.stream()
                    .filter(deptDTO -> deptDTO.getId().equals(param.getId()))
                    .collect(Collectors.toList());
            info.add(supervisionDetailsAdd(dept.get(0), Collections.singletonList(param.getId()), param));
        } else {
            for (DeptDTO deptDTO : directDeptInfos) {
                //筛选上级部门pids包含该id的所有部门
                List<DeptDTO> descendantDeptDTO = deptInfos.stream()
                        .filter(d -> d.getPids().contains(deptDTO.getId()))
                        .collect(Collectors.toList());
                //形成需要查询监测点的部门索引
                List<String> indexes = descendantDeptDTO.stream()
                        .map(DeptDTO::getId)
                        .distinct()
                        .collect(Collectors.toList());
                indexes.add(deptDTO.getId());
                info.add(supervisionDetailsAdd(deptDTO, indexes, param));
            }
        }
        return info;
    }

    @Override
    public GridDiagramVO.City getSupervisionCityDetailsData(StatisticsBizBaseParam param) {
        List<String> deptIds = deptFeignClient.getDepSonIdByDeptId(param.getId()).getData();
        GridDiagramVO.City City = new GridDiagramVO.City();
        //在线监测问题
        List<LineWarning> lineWarning = lineWarningService.list(new LambdaQueryWrapper<LineWarning>()
                .in(LineWarning::getDeptId, deptIds)
                .isNotNull(LineWarning::getStep)
                .ge(StrUtil.isNotBlank(param.getStartTime()), LineWarning::getCreateTime, DateUtil.beginOfDay(DateUtil.parse(param.getStartTime())))
                .le(StrUtil.isNotBlank(param.getEndTime()), LineWarning::getCreateTime, DateUtil.endOfDay(DateUtil.parse(param.getEndTime())))
        );
        List<String> lineWarningList = lineWarning.stream().map(LineWarning::getLeafletId).distinct().collect(Collectors.toList());
        //用户投诉问题(添加出来就是有问题的)
        List<SupervisionUserComplaintPO> userComplaintList = userComplaintPOService.list(new LambdaQueryWrapper<SupervisionUserComplaintPO>()
                .and(x->x .in(SupervisionUserComplaintPO::getDutyOrgId, deptIds)
                        .eq(SupervisionUserComplaintPO::getState, DataStateEnum.ENABLE.getCode())
                        .ge(StrUtil.isNotBlank(param.getStartTime()), SupervisionUserComplaintPO::getCreateTime, DateUtil.beginOfDay(DateUtil.parse(param.getStartTime())))
                        .le(StrUtil.isNotBlank(param.getEndTime()), SupervisionUserComplaintPO::getCreateTime, DateUtil.endOfDay(DateUtil.parse(param.getEndTime()))))
                .or(x->x.eq(SupervisionUserComplaintPO::getDealState,0)
                        .in(SupervisionUserComplaintPO::getDutyOrgId, deptIds)
                        .eq(SupervisionUserComplaintPO::getState, DataStateEnum.ENABLE.getCode())
                )

        );
        //计划问题(有问题的单子)
        List<SurveyTest> surveyTestList = surveyTestService.list(new LambdaQueryWrapper<SurveyTest>()
                .and(x->x.in(SurveyTest::getDeptId, deptIds)
                        .eq(SurveyTest::getState, DataStateEnum.ENABLE.getCode())
                        .eq(SurveyTest::getStatus, FlowStatusEnum.APPROVE.getCode())
                        .eq(SurveyTest::getProblemFlag, 1)
                        .ge(StrUtil.isNotBlank(param.getStartTime()), SurveyTest::getCreateTime, DateUtil.beginOfDay(DateUtil.parse(param.getStartTime())))
                        .le(StrUtil.isNotBlank(param.getEndTime()), SurveyTest::getCreateTime, DateUtil.endOfDay(DateUtil.parse(param.getEndTime()))))
                .or(x->x.eq(SurveyTest::getDealState,0)
                        .in(SurveyTest::getDeptId, deptIds)
                        .eq(SurveyTest::getState, DataStateEnum.ENABLE.getCode())
                        .eq(SurveyTest::getStatus, FlowStatusEnum.APPROVE.getCode())
                        .eq(SurveyTest::getProblemFlag, 1)

                )
        );
        //试运行问题单子
        List<String> runWarningsIds =  warningsMapper.selectWarningsIds(deptIds, param);


        //根据问题单id查询已关联工单
        List<String> problemIds = userComplaintList.stream().map(SupervisionUserComplaintPO::getId).collect(Collectors.toList());
        problemIds.addAll(surveyTestList.stream().map(SurveyTest::getId).collect(Collectors.toList()));
        problemIds.addAll(lineWarningList);
        problemIds.addAll(runWarningsIds);

        List<WarningLeaflet> list =new ArrayList<>();
        if (CollUtil.isNotEmpty(problemIds)) {
            list.addAll(warningLeafletService.list(new LambdaQueryWrapper<WarningLeaflet>()
                    .and(x->x
                            .in(WarningLeaflet::getProblemId, problemIds)
                            .or()
                            .in(WarningLeaflet::getId, problemIds)
                    )
                    .in(WarningLeaflet::getState, 1))
            );
        }
        //在线监测问题
        GridDiagramVO warnVo=new GridDiagramVO();
        List<WarningLeaflet> warn = list.stream().filter(x -> lineWarningList.contains(x.getId())).collect(Collectors.toList());
        warnVo.setAbnormalNum(lineWarningList.size());
        warnVo.setAssociatedNum(warn.size());
        warnVo.setConversionNum(warnVo.getAbnormalNum() == 0 ? 0.0f : NumberUtil.round(warn.size() * 100.0 / warnVo.getAbnormalNum(), 2).floatValue());
        List<String> handleList = warn.stream().filter(x -> x.getStatus() == 2).map(WarningLeaflet::getId).collect(Collectors.toList());
        warnVo.setWorkNum(warn.size());
        warnVo.setProcessedNum(handleList.size());
        warnVo.setDisposalNum(warn.isEmpty() ? 0.0f : NumberUtil.round(handleList.size() * 100.0 / warn.size(), 2).floatValue());

        //用户投诉问题(添加出来就是有问题的)
        GridDiagramVO userVo=new GridDiagramVO();
        List<WarningLeaflet> user = list.stream().filter(x -> userComplaintList.stream().map(SupervisionUserComplaintPO::getId)
                .collect(Collectors.toList()).contains(x.getProblemId())).collect(Collectors.toList());
        userVo.setAbnormalNum(userComplaintList.size());
        userVo.setAssociatedNum(user.size());
        userVo.setConversionNum(userVo.getAbnormalNum() == 0 ? 0.0f : NumberUtil.round(user.size() * 100.0 / userVo.getAbnormalNum(), 2).floatValue());
        List<String> userHandleList = user.stream().filter(x -> x.getStatus() == 2).map(WarningLeaflet::getId).collect(Collectors.toList());
        userVo.setWorkNum(user.size());
        userVo.setProcessedNum(userHandleList.size());
        userVo.setDisposalNum(user.isEmpty() ? 0.0f : NumberUtil.round(userHandleList.size() * 100.0 / user.size(), 2).floatValue());

        //计划问题(有问题的单子)
        GridDiagramVO surveyVo=new GridDiagramVO();
        List<WarningLeaflet> survey = list.stream().filter(x -> surveyTestList.stream().map(SurveyTest::getId)
                .collect(Collectors.toList()).contains(x.getProblemId())).collect(Collectors.toList());
        surveyVo.setAbnormalNum(surveyTestList.size());
        surveyVo.setAssociatedNum(survey.size());
        surveyVo.setConversionNum(surveyVo.getAbnormalNum() == 0 ? 0.0f : NumberUtil.round(survey.size() * 100.0 / surveyVo.getAbnormalNum(), 2).floatValue());
        List<String> surveyHandleList = survey.stream().filter(x -> x.getStatus() == 2).map(WarningLeaflet::getId).collect(Collectors.toList());
        surveyVo.setWorkNum(survey.size());
        surveyVo.setProcessedNum(surveyHandleList.size());
        surveyVo.setDisposalNum(survey.isEmpty() ? 0.0f : NumberUtil.round(surveyHandleList.size() * 100.0 / survey.size(), 2).floatValue());

        //试运行监测点问题
        GridDiagramVO trialRunVo=new GridDiagramVO();
        List<WarningLeaflet> trialRun = list.stream().filter(x -> runWarningsIds.contains(x.getProblemId())).collect(Collectors.toList());
        trialRunVo.setAbnormalNum(runWarningsIds.size());
        trialRunVo.setAssociatedNum(trialRun.size());
        trialRunVo.setConversionNum(trialRunVo.getAbnormalNum() == 0 ? 0.0f : NumberUtil.round(trialRun.size() * 100.0 / trialRunVo.getAbnormalNum(), 2).floatValue());
        List<String> trialRunHandleList = trialRun.stream().filter(x -> x.getStatus() == 2).map(WarningLeaflet::getId).collect(Collectors.toList());
        trialRunVo.setWorkNum(trialRun.size());
        trialRunVo.setProcessedNum(trialRunHandleList.size());
        trialRunVo.setDisposalNum(trialRun.isEmpty() ? 0.0f : NumberUtil.round(trialRunHandleList.size() * 100.0 / trialRun.size(), 2).floatValue());

        City.setOnLine(warnVo);
        City.setUser(userVo);
        City.setSurvey(surveyVo);
        City.setTrialRun(trialRunVo);
        return City;
    }

    /**
     * @param deptDTO   子集部门
     * @param ids       子集下所有部门信息
     * @param baseParam 查询条件
     */
    private GridDiagramVO.Info supervisionDetailsAdd(DeptDTO deptDTO, List<String> ids, StatisticsBizBaseParam baseParam) {
        GridDiagramVO.Info gridDiagramVO = new GridDiagramVO.Info();
        if (ObjectUtil.isNotNull(deptDTO)) {
            gridDiagramVO.setOrgName(deptDTO.getName());
        }
        //在线监测问题
        List<LineWarning> lineWarning = lineWarningService.list(new LambdaQueryWrapper<LineWarning>()
                .in(LineWarning::getDeptId, ids)
                .isNotNull(LineWarning::getStep)
                .ge(StrUtil.isNotBlank(baseParam.getStartTime()), LineWarning::getCreateTime, DateUtil.beginOfDay(DateUtil.parse(baseParam.getStartTime())))
                .le(StrUtil.isNotBlank(baseParam.getEndTime()), LineWarning::getCreateTime, DateUtil.endOfDay(DateUtil.parse(baseParam.getEndTime())))
        );
        List<String> lineWarningList = lineWarning.stream().map(LineWarning::getLeafletId).distinct().collect(Collectors.toList());
        gridDiagramVO.setOnLineNum(lineWarningList.size());
        //用户投诉问题(添加出来就是有问题的)
        List<SupervisionUserComplaintPO> userComplaintList = userComplaintPOService.list(new LambdaQueryWrapper<SupervisionUserComplaintPO>()
                .and(x->x.in(SupervisionUserComplaintPO::getDutyOrgId, ids)
                                .eq(SupervisionUserComplaintPO::getState, 1)
                                .ge(StrUtil.isNotBlank(baseParam.getStartTime()), SupervisionUserComplaintPO::getCreateTime, DateUtil.beginOfDay(DateUtil.parse(baseParam.getStartTime())))
                                .le(StrUtil.isNotBlank(baseParam.getEndTime()), SupervisionUserComplaintPO::getCreateTime, DateUtil.endOfDay(DateUtil.parse(baseParam.getEndTime()))))
                .or(x->x.eq(SupervisionUserComplaintPO::getDealState,0)
                        .in(SupervisionUserComplaintPO::getDutyOrgId, ids)
                        .eq(SupervisionUserComplaintPO::getState, 1)
                )
        );
        gridDiagramVO.setUserNum(userComplaintList.size());
        //计划问题(有问题的单子)
        List<SurveyTest> surveyTestList = surveyTestService.list(new LambdaQueryWrapper<SurveyTest>()
                .and(x->x.in(SurveyTest::getDeptId, ids)
                                .eq(SurveyTest::getState, DataStateEnum.ENABLE.getCode())
                                .eq(SurveyTest::getStatus, FlowStatusEnum.APPROVE.getCode())
                                .eq(SurveyTest::getProblemFlag, 1)
                                .ge(StrUtil.isNotBlank(baseParam.getStartTime()), SurveyTest::getCreateTime, DateUtil.beginOfDay(DateUtil.parse(baseParam.getStartTime())))
                                .le(StrUtil.isNotBlank(baseParam.getEndTime()), SurveyTest::getCreateTime, DateUtil.endOfDay(DateUtil.parse(baseParam.getEndTime()))))
                .or(x->x.eq(SurveyTest::getDealState,0)
                        .in(SurveyTest::getDeptId, ids)
                        .eq(SurveyTest::getState, DataStateEnum.ENABLE.getCode())
                        .eq(SurveyTest::getStatus, FlowStatusEnum.APPROVE.getCode())
                        .eq(SurveyTest::getProblemFlag, 1)
                )

        );
        gridDiagramVO.setSurveyNum(surveyTestList.size());

        //试运行问题单子
        List<String> runWarningsIds =  warningsMapper.selectWarningsIds(ids, baseParam);
        gridDiagramVO.setTrialRunNum(runWarningsIds.size());


        gridDiagramVO.setAbnormalNum(lineWarningList.size() + userComplaintList.size() + surveyTestList.size()+ runWarningsIds.size());
        //根据问题单id查询已关联工单
        List<String> problemIds = userComplaintList.stream().map(SupervisionUserComplaintPO::getId).collect(Collectors.toList());
        problemIds.addAll(surveyTestList.stream().map(SurveyTest::getId).collect(Collectors.toList()));
        problemIds.addAll(lineWarningList);
        problemIds.addAll(runWarningsIds);


        if (CollUtil.isNotEmpty(problemIds)) {
            List<WarningLeaflet> list = warningLeafletService.list(new LambdaQueryWrapper<WarningLeaflet>()
                            .and(x->x
                                    .in(WarningLeaflet::getProblemId, problemIds)
                                    .or()
                                    .in(WarningLeaflet::getId, problemIds)
                            )
                    .in(WarningLeaflet::getState, 1)
            );
            gridDiagramVO.setAssociatedNum(list.size());
            gridDiagramVO.setConversionNum(gridDiagramVO.getAbnormalNum() == 0 ? 0.0f : NumberUtil.round(list.size() * 100.0 / gridDiagramVO.getAbnormalNum(), 2).floatValue());
            List<String> handleList = list.stream().filter(x -> x.getStatus() == 2).map(WarningLeaflet::getId).collect(Collectors.toList());
            gridDiagramVO.setWorkNum(list.size());
            gridDiagramVO.setProcessedNum(handleList.size());
            gridDiagramVO.setDisposalNum(list.isEmpty() ? 0.0f : NumberUtil.round(handleList.size() * 100.0 / list.size(), 2).floatValue());

        } else {
            gridDiagramVO.setAssociatedNum(0);
            gridDiagramVO.setConversionNum(0.0f);
            gridDiagramVO.setWorkNum(0);
            gridDiagramVO.setProcessedNum(0);
            gridDiagramVO.setDisposalNum(0.0f);
        }
        return gridDiagramVO;
    }
}
