package com.gci.boot.modules.statis.service.impl;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Segment;
import cn.hutool.core.util.PageUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gci.boot.modules.projects.entity.Projects;
import com.gci.boot.modules.projects.service.IProjectsService;
import com.gci.boot.modules.statis.service.BusinessService;
import com.gci.boot.modules.statis.vo.*;
import com.gci.boot.modules.system.service.ISysDictService;
import com.gci.boot.modules.system.vo.DictModel;
import com.gci.boot.modules.vehicles.mapper.TbAnnualInspectionInfoMapper;
import com.gci.boot.modules.vehicles.mapper.TbInsuranceMapper;
import com.gci.boot.modules.vehicles.mapper.TbRepairInfoMapper;
import com.gci.boot.modules.vehicles.mapper.TbUpkeepBillMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class BusinessServiceImpl implements BusinessService {

    @Autowired
    private TbRepairInfoMapper repairInfoMapper;
    @Autowired
    private TbInsuranceMapper insuranceMapper;
    @Autowired
    private TbUpkeepBillMapper upkeepBillMapper;
    @Autowired
    private TbAnnualInspectionInfoMapper annualInspectionInfoMapper;
    @Autowired
    private IProjectsService projectsService;
    @Autowired
    private ISysDictService sysDictService;

    @Override
    public IPage<BusinessStatisVo> page(Page<BusinessStatisVo> page, StatisParamVO vo) {
        if("1".equals(vo.getStatisType())){
            vo.setStatisTime("YYYY-MM-DD");
        }else if("2".equals(vo.getStatisType())){
            vo.setStatisTime("YYYY-MM");
        }else if("3".equals(vo.getStatisType())){
            vo.setStatisTime("YYYY");
        }else{
            vo.setStatisTime("YYYY-MM-DD");
        }

        List<RepairStatisVO> repairList = new ArrayList<>();
        List<InsuranceStatisVo> insuranceList = new ArrayList<>();
        List<UpkeepStatisVO> upkeepList = new ArrayList<>();
        List<AnnualInspectionInfoStatisVo> annualInspectionInfoList = new ArrayList<>();

        String businessType = vo.getBusinessType();
        if (StrUtil.isBlank(businessType)) {
            repairList = repairInfoMapper.findStatisRepairAllGroupByProject(vo);
            insuranceList = insuranceMapper.findStatisInsuranceByProject(vo);
            upkeepList = upkeepBillMapper.findStatisUpkeepAllGroupByProject(vo);
            annualInspectionInfoList = annualInspectionInfoMapper.findStatisAnnualInspectionInfoAllGroupByProject(vo);
        } else if ("1".equals(businessType)) {
            repairList = repairInfoMapper.findStatisRepairAllGroupByProject(vo);
        } else if ("2".equals(businessType)) {
            insuranceList = insuranceMapper.findStatisInsuranceByProject(vo);
        } else if ("3".equals(businessType)) {
            upkeepList = upkeepBillMapper.findStatisUpkeepAllGroupByProject(vo);
        } else if ("4".equals(businessType)) {
            annualInspectionInfoList = annualInspectionInfoMapper.findStatisAnnualInspectionInfoAllGroupByProject(vo);
        }

//        List<Projects> projects = projectsService.list(new LambdaQueryWrapper<Projects>().orderByAsc(Projects::getCreateTime));
        List<Projects> projects = projectsService.getAllProjectsAuth();
        ArrayList<BusinessStatisVo> businessStatisVos = getBusinessStatisVos(projects,repairList, insuranceList, upkeepList, annualInspectionInfoList);
        PageUtil.setOneAsFirstPageNo();
        int totalPage = PageUtil.totalPage(businessStatisVos.size(), Convert.toInt(page.getSize()));
        if (page.getCurrent() > totalPage) {
            page.setCurrent(totalPage);
        }
        page.setTotal(businessStatisVos.size());
        page.setPages(totalPage);
        Segment<Integer> integerSegment = PageUtil.toSegment(Convert.toInt(page.getCurrent()), Convert.toInt(page.getSize()));
        Integer endIndex = integerSegment.getEndIndex();
        if (endIndex > businessStatisVos.size()) {
            endIndex = businessStatisVos.size();
        }
        page.setRecords(businessStatisVos.subList(integerSegment.getStartIndex(), endIndex));
        return page;
    }

    @Override
    public List<List<Object>> getAll(StatisParamVO vo) {
        if("1".equals(vo.getStatisType())){
            vo.setStatisTime("YYYY-MM-DD");
        }else if("2".equals(vo.getStatisType())){
            vo.setStatisTime("YYYY-MM");
        }else if("3".equals(vo.getStatisType())){
            vo.setStatisTime("YYYY");
        }else{
            vo.setStatisTime("YYYY-MM-DD");
        }

        List<List<Object>> datas = new ArrayList<>();

        List<RepairStatisVO> repairList = new ArrayList<>();
        List<InsuranceStatisVo> insuranceList = new ArrayList<>();
        List<UpkeepStatisVO> upkeepList = new ArrayList<>();
        List<AnnualInspectionInfoStatisVo> annualInspectionInfoList = new ArrayList<>();

        String businessType = vo.getBusinessType();
        if (StrUtil.isBlank(businessType)) {
            repairList = repairInfoMapper.findStatisRepairAllGroupByProject(vo);
            insuranceList = insuranceMapper.findStatisInsuranceByProject(vo);
            upkeepList = upkeepBillMapper.findStatisUpkeepAllGroupByProject(vo);
            annualInspectionInfoList = annualInspectionInfoMapper.findStatisAnnualInspectionInfoAllGroupByProject(vo);
        } else if ("1".equals(businessType)) {
            repairList = repairInfoMapper.findStatisRepairAllGroupByProject(vo);
        } else if ("2".equals(businessType)) {
            insuranceList = insuranceMapper.findStatisInsuranceByProject(vo);
        } else if ("3".equals(businessType)) {
            upkeepList = upkeepBillMapper.findStatisUpkeepAllGroupByProject(vo);
        } else if ("4".equals(businessType)) {
            annualInspectionInfoList = annualInspectionInfoMapper.findStatisAnnualInspectionInfoAllGroupByProject(vo);
        }

//        List<Projects> projects = projectsService.list(new LambdaQueryWrapper<Projects>().orderByAsc(Projects::getCreateTime));
        List<Projects> projects = projectsService.getAllProjectsAuth();
        ArrayList<BusinessStatisVo> businessStatisVos = getBusinessStatisVos(projects,repairList, insuranceList, upkeepList, annualInspectionInfoList);

        List<DictModel> dictModels = sysDictService.queryDictItemsByCode("business_type");
        Map<String, String> collect = dictModels.stream().collect(Collectors.toMap(DictModel::getValue, DictModel::getText));
        for (BusinessStatisVo businessStatisVo : businessStatisVos) {
            List<Object> data = new ArrayList<>();
            data.add(collect.getOrDefault(businessStatisVo.getBusinessType(),businessStatisVo.getBusinessType()+"无匹配字典"));
            data.add(businessStatisVo.getStatisTime());
            for (ColumnItemVo2 columnItemVo2 : businessStatisVo.getColList()) {
                data.add(columnItemVo2.getCount());
            }
            datas.add(data);
        }

        return datas;
    }

    private ArrayList<BusinessStatisVo> getBusinessStatisVos(List<Projects> projects, List<RepairStatisVO> repairList, List<InsuranceStatisVo> insuranceList, List<UpkeepStatisVO> upkeepList, List<AnnualInspectionInfoStatisVo> annualInspectionInfoList) {

        Map<String, BusinessStatisVo> map = new HashMap<>();
        Map<String, List<RepairStatisVO>> repairListMap = CollStreamUtil.groupByKey(repairList, RepairStatisVO::getStatisTime);
        for (Map.Entry<String, List<RepairStatisVO>> repairListMapEntry : repairListMap.entrySet()) {
            String key = repairListMapEntry.getKey();
            List<RepairStatisVO> value = repairListMapEntry.getValue();
            BusinessStatisVo businessStatisVo = new BusinessStatisVo();
            //维修
            businessStatisVo.setBusinessType("1");
            businessStatisVo.setStatisTime(repairListMapEntry.getKey());
            ArrayList<ColumnItemVo2> columnItemVo2s = new ArrayList<>();
            Map<String, Double> collect = value.stream().collect(Collectors.toMap(RepairStatisVO::getProjectId, RepairStatisVO::getRepairAmount));
            for (Projects project : projects) {
                ColumnItemVo2 columnItemVo = new ColumnItemVo2();
                columnItemVo.setColName(project.getProjectName());
                columnItemVo.setCount(collect.getOrDefault(project.getId(),0.0));
                columnItemVo2s.add(columnItemVo);
            }
            businessStatisVo.setColList(columnItemVo2s);
            map.put(key + "1",businessStatisVo);
        }

        Map<String, List<InsuranceStatisVo>> insuranceListMap = CollStreamUtil.groupByKey(insuranceList, InsuranceStatisVo::getStatisTime);
        for (Map.Entry<String, List<InsuranceStatisVo>> insuranceListEntry : insuranceListMap.entrySet()) {
            String key = insuranceListEntry.getKey();
            List<InsuranceStatisVo> value = insuranceListEntry.getValue();
            BusinessStatisVo businessStatisVo = new BusinessStatisVo();
            //保险
            businessStatisVo.setBusinessType("2");
            businessStatisVo.setStatisTime(insuranceListEntry.getKey());
            ArrayList<ColumnItemVo2> columnItemVo2s = new ArrayList<>();
            Map<String, Double> collect = value.stream().collect(Collectors.toMap(InsuranceStatisVo::getProjectId, InsuranceStatisVo::getTotalPrice));
            for (Projects project : projects) {
                ColumnItemVo2 columnItemVo = new ColumnItemVo2();
                columnItemVo.setColName(project.getProjectName());
                columnItemVo.setCount(collect.getOrDefault(project.getId(),0.0));
                columnItemVo2s.add(columnItemVo);
            }
            businessStatisVo.setColList(columnItemVo2s);
            map.put(key + "2",businessStatisVo);
        }
        Map<String, List<UpkeepStatisVO>> upkeepListMap = CollStreamUtil.groupByKey(upkeepList, UpkeepStatisVO::getStatisTime);
        for (Map.Entry<String, List<UpkeepStatisVO>> upkeepListEntry : upkeepListMap.entrySet()) {
            String key = upkeepListEntry.getKey();
            List<UpkeepStatisVO> value = upkeepListEntry.getValue();
            BusinessStatisVo businessStatisVo = new BusinessStatisVo();
            //保养
            businessStatisVo.setBusinessType("3");
            businessStatisVo.setStatisTime(upkeepListEntry.getKey());
            ArrayList<ColumnItemVo2> columnItemVo2s = new ArrayList<>();
            Map<String, Double> collect = value.stream().collect(Collectors.toMap(UpkeepStatisVO::getProjectId, UpkeepStatisVO::getUpkeepAmount));
            for (Projects project : projects) {
                ColumnItemVo2 columnItemVo = new ColumnItemVo2();
                columnItemVo.setColName(project.getProjectName());
                columnItemVo.setCount(collect.getOrDefault(project.getId(),0.0));
                columnItemVo2s.add(columnItemVo);
            }
            businessStatisVo.setColList(columnItemVo2s);
            map.put(key + "3",businessStatisVo);
        }


        Map<String, List<AnnualInspectionInfoStatisVo>> annualInspectionInfoListMap = CollStreamUtil.groupByKey(annualInspectionInfoList, AnnualInspectionInfoStatisVo::getStatisTime);
        for (Map.Entry<String, List<AnnualInspectionInfoStatisVo>> annualInspectionInfoListEntry : annualInspectionInfoListMap.entrySet()) {
            String key = annualInspectionInfoListEntry.getKey();
            List<AnnualInspectionInfoStatisVo> value = annualInspectionInfoListEntry.getValue();
            BusinessStatisVo businessStatisVo = new BusinessStatisVo();
            //维修
            businessStatisVo.setBusinessType("4");
            businessStatisVo.setStatisTime(annualInspectionInfoListEntry.getKey());
            ArrayList<ColumnItemVo2> columnItemVo2s = new ArrayList<>();
            Map<String, Double> collect = value.stream().collect(Collectors.toMap(AnnualInspectionInfoStatisVo::getProjectId, AnnualInspectionInfoStatisVo::getInspectionAmount));
            for (Projects project : projects) {
                ColumnItemVo2 columnItemVo = new ColumnItemVo2();
                columnItemVo.setColName(project.getProjectName());
                columnItemVo.setCount(collect.getOrDefault(project.getId(),0.0));
                columnItemVo2s.add(columnItemVo);
            }
            businessStatisVo.setColList(columnItemVo2s);
            map.put(key + "4",businessStatisVo);
        }
        ArrayList<BusinessStatisVo> businessStatisVos = new ArrayList<>(map.values());
        if (!businessStatisVos.isEmpty()) {
            businessStatisVos.sort(Comparator.comparing(BusinessStatisVo::getStatisTime).thenComparing(BusinessStatisVo::getBusinessType));
        }
        return businessStatisVos;
    }
}
