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

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Segment;
import cn.hutool.core.util.PageUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gci.boot.modules.projects.service.IProjectsService;
import com.gci.boot.modules.statis.service.ProjectStatisService;
import com.gci.boot.modules.statis.vo.*;
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.*;

@Service
@Slf4j
public class ProjectStatisServiceImpl implements ProjectStatisService {

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


    @Override
    public IPage<ProjectStatisVo> page(Page<ProjectStatisVo> page, StatisParamVO vo) {
        ArrayList<ProjectStatisVo> projectStatisVos = getProjectStatisVos(vo);

        if (projectStatisVos.size() == 0) {
            return page;
        }
        PageUtil.setOneAsFirstPageNo();
        int totalPage = PageUtil.totalPage(projectStatisVos.size(), Convert.toInt(page.getSize()));
        if (page.getCurrent() > totalPage) {
            page.setCurrent(totalPage);
        }
        page.setTotal(projectStatisVos.size());
        page.setPages(totalPage);
        Segment<Integer> integerSegment = PageUtil.toSegment(Convert.toInt(page.getCurrent()), Convert.toInt(page.getSize()));
        Integer endIndex = integerSegment.getEndIndex();
        if (endIndex > projectStatisVos.size()) {
            endIndex = projectStatisVos.size();
        }
        page.setRecords(projectStatisVos.subList(integerSegment.getStartIndex(), endIndex));
        return page;
    }

    private ArrayList<ProjectStatisVo> getProjectStatisVos(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<String> listProjectIds = projectsService.queryProjectListOfUser();

        List<RepairStatisVO> repairList = repairInfoMapper.findStatisRepairAll(vo,listProjectIds);
        List<UpkeepStatisVO> upkeepList = upkeepBillMapper.findStatisUpkeepAll(vo,listProjectIds);
        List<InsuranceStatisVo> insuranceList = insuranceMapper.findStatisInsuranceAll(vo,listProjectIds);
        List<AnnualInspectionInfoStatisVo> annualInspectionInfoList = annualInspectionInfoMapper.findStatisAnnualInspectionInfoAll(vo,listProjectIds);

        Map<String, ProjectStatisVo> map = getStringProjectStatisVoMap(repairList, upkeepList, insuranceList, annualInspectionInfoList);
        ArrayList<ProjectStatisVo> projectStatisVos = new ArrayList<>(map.values());
        if (!projectStatisVos.isEmpty()) {
            projectStatisVos.sort(Comparator.comparing(ProjectStatisVo::getStatisTime));
        }
        return projectStatisVos;
    }

    @Override
    public List<ProjectStatisVo> getAll(StatisParamVO vo) {
        ArrayList<ProjectStatisVo> projectStatisVos = getProjectStatisVos(vo);
        return projectStatisVos;
    }

    private Map<String, ProjectStatisVo> getStringProjectStatisVoMap(List<RepairStatisVO> repairList, List<UpkeepStatisVO> upkeepList, List<InsuranceStatisVo> insuranceList, List<AnnualInspectionInfoStatisVo> annualInspectionInfoList) {
        //创建一个Map，用于存储项目Id，项目名称和车辆类型为键，ReportListVo为值
        Map<String, ProjectStatisVo> map = new HashMap<>();
        for (RepairStatisVO to : repairList) {
            //生成一个键，由项目Id，项目名称和车辆类型组成，用逗号分隔
            String key = to.getProjectId() + "," + to.getVehicleType() + "," + to.getStatisTime();
            //如果Map中已经存在该键，说明已经有一个ReportListVo对象，那么只需要更新其维修统计字段
            if (map.containsKey(key)) {
                ProjectStatisVo rl = map.get(key);
                rl.setRepairAmount(rl.getRepairAmount()+to.getRepairAmount());
            } else {
                //否则，创建一个新的ReportListVo对象，并设置其项目Id，项目名称，车辆类型和维修统计字段
                ProjectStatisVo rl = new ProjectStatisVo();
                rl.setProjectId(to.getProjectId());
                rl.setVehicleType(to.getVehicleType());
                rl.setStatisTime(to.getStatisTime());
                rl.setRepairAmount(to.getRepairAmount());
                //将新的ReportListVo对象放入Map中
                map.put(key, rl);
            }
        }
        for (UpkeepStatisVO to : upkeepList) {
            //生成一个键，由项目Id，项目名称和车辆类型组成，用逗号分隔
            String key = to.getProjectId() + "," + to.getVehicleType() + "," + to.getStatisTime();
            //如果Map中已经存在该键，说明已经有一个ReportListVo对象，那么只需要更新其维修统计字段
            if (map.containsKey(key)) {
                ProjectStatisVo rl = map.get(key);
                rl.setUpkeepAmount(rl.getUpkeepAmount()+ to.getUpkeepAmount());
            } else {
                //否则，创建一个新的ReportListVo对象，并设置其项目Id，项目名称，车辆类型和维修统计字段
                ProjectStatisVo rl = new ProjectStatisVo();
                rl.setProjectId(to.getProjectId());
                rl.setVehicleType(to.getVehicleType());
                rl.setStatisTime(to.getStatisTime());
                rl.setUpkeepAmount(to.getUpkeepAmount());
                //将新的ReportListVo对象放入Map中
                map.put(key, rl);
            }
        }
        for (InsuranceStatisVo to : insuranceList) {
            //生成一个键，由项目Id，项目名称和车辆类型组成，用逗号分隔
            String key = to.getProjectId() + "," + to.getVehicleType() + "," + to.getStatisTime();
            //如果Map中已经存在该键，说明已经有一个ReportListVo对象，那么只需要更新其维修统计字段
            if (map.containsKey(key)) {
                ProjectStatisVo rl = map.get(key);
                rl.setInsuranceAmount(rl.getInsuranceAmount()+ to.getTotalPrice());
            } else {
                //否则，创建一个新的ReportListVo对象，并设置其项目Id，项目名称，车辆类型和维修统计字段
                ProjectStatisVo rl = new ProjectStatisVo();
                rl.setProjectId(to.getProjectId());
                rl.setVehicleType(to.getVehicleType());
                rl.setStatisTime(to.getStatisTime());
                rl.setInsuranceAmount(to.getTotalPrice());
                //将新的ReportListVo对象放入Map中
                map.put(key, rl);
            }
        }
        for (AnnualInspectionInfoStatisVo to : annualInspectionInfoList) {
            //生成一个键，由项目Id，项目名称和车辆类型组成，用逗号分隔
            String key = to.getProjectId() + "," + to.getVehicleType() + "," + to.getStatisTime();
            //如果Map中已经存在该键，说明已经有一个ReportListVo对象，那么只需要更新其维修统计字段
            if (map.containsKey(key)) {
                ProjectStatisVo rl = map.get(key);
                rl.setInspectionAmount(rl.getInspectionAmount() + to.getInspectionAmount());
            } else {
                //否则，创建一个新的ReportListVo对象，并设置其项目Id，项目名称，车辆类型和维修统计字段
                ProjectStatisVo rl = new ProjectStatisVo();
                rl.setProjectId(to.getProjectId());
                rl.setVehicleType(to.getVehicleType());
                rl.setStatisTime(to.getStatisTime());
                rl.setInspectionAmount(to.getInspectionAmount());
                //将新的ReportListVo对象放入Map中
                map.put(key, rl);
            }
        }
        return map;
    }
}
