package com.yeejoin.amos.boot.module.jyjc.biz.service.impl;

import cn.hutool.core.date.DateUtil;
import com.yeejoin.amos.boot.module.common.api.dto.DPFilterParamDto;
import com.yeejoin.amos.boot.module.jyjc.api.dto.InspectTimeCountDto;
import com.yeejoin.amos.boot.module.jyjc.api.enums.BizTypeEnum;
import com.yeejoin.amos.boot.module.jyjc.api.mapper.JyjcInspectionApplicationEquipMapper;
import com.yeejoin.amos.boot.module.ymt.api.dto.EquipmentCategoryDto;
import com.yeejoin.amos.boot.module.ymt.api.mapper.EquipmentCategoryMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 大屏统计实现类
 *
 * @author Administrator
 */
@Service
public class DPStatisticsServiceImpl {

    /**
     * 压力容器设备种类
     */
    private final static String EQU_LIST_CYLINDER = "2000";

    /**
     * 气瓶设备类别
     */
    private final static String EQU_CATEGORY_CYLINDER = "2300";

    private EquipmentCategoryMapper equipmentCategoryMapper;

    private JyjcInspectionApplicationEquipMapper inspectionApplicationEquipMapper;

    public DPStatisticsServiceImpl(EquipmentCategoryMapper equipmentCategoryMapper, JyjcInspectionApplicationEquipMapper inspectionApplicationEquipMapper) {
        this.equipmentCategoryMapper = equipmentCategoryMapper;
        this.inspectionApplicationEquipMapper = inspectionApplicationEquipMapper;
    }


    public Map<String, Object> inspectTimeCountByTypeAndEquList(DPFilterParamDto dpFilterParamDto) {
        // 1.查询条件构造未上送时间时，默认查询数据为近一个月数据
        this.setDefaultFilter(dpFilterParamDto);
        // 2.按照前端约定格式返回数据
        Map<String, Object> result = new HashMap<>();
        //2.1 图列数据构造
        List<BizTypeEnum> bizTypeEnums = getBizTypeList();
        result.put("legendData", this.getLegendData(bizTypeEnums));
        // 8大类设备种类
        List<EquipmentCategoryDto> equipmentCategoryDtos = equipmentCategoryMapper.selectClassify();
        //2.2 x轴数据构造
        result.put("xdata", this.getXData(equipmentCategoryDtos));
        //2.3 y轴数据构造
        this.buildYData(result, bizTypeEnums, dpFilterParamDto, equipmentCategoryDtos);
        return result;
    }

    private void buildYData(Map<String, Object> result, List<BizTypeEnum> bizTypeEnums, DPFilterParamDto dpFilterParamDto, List<EquipmentCategoryDto> equipmentCategoryDtos) {
        // 待统计的数据本来sql可以单独统计，但是要求气瓶单独从压力容器里拎出来，与八大类同级，故java处理
        List<InspectTimeCountDto> inspectTimeCountDtos = inspectionApplicationEquipMapper.countInspectTimeCountByTypeAndEquList(dpFilterParamDto);
        bizTypeEnums.forEach(bizTypeEnum -> {
            result.put(bizTypeEnum.getCode(), this.countNumByBizTypeAndEquList(equipmentCategoryDtos, bizTypeEnum.getCode(), inspectTimeCountDtos));
        });
    }

    private List<Integer> countNumByBizTypeAndEquList(List<EquipmentCategoryDto> equipmentCategoryDtos, String bizType, List<InspectTimeCountDto> inspectTimeCountDtos) {
        List<Integer> item = new ArrayList<>();
        // 8大类数据统计数量
        equipmentCategoryDtos.forEach(equipmentCategoryDto -> {
            int num = 0;
            // 压力容器要去掉气瓶2300，气瓶单独统计
            if (EQU_LIST_CYLINDER.equals(equipmentCategoryDto.getCode())) {
                num = inspectTimeCountDtos.stream().filter(c -> c.getBizType().equals(bizType) && c.getEquList().equals(equipmentCategoryDto.getCode()) && !EQU_CATEGORY_CYLINDER.equals(c.getEquCategory())).mapToInt(InspectTimeCountDto::getNum).sum();
            } else {
                num = inspectTimeCountDtos.stream().filter(c -> c.getBizType().equals(bizType) && c.getEquList().equals(equipmentCategoryDto.getCode())).mapToInt(InspectTimeCountDto::getNum).sum();
            }
            item.add(num);
        });
        // 再增加气瓶(设备类别2300)专项
        int num = inspectTimeCountDtos.stream().filter(c -> c.getBizType().equals(bizType) && EQU_CATEGORY_CYLINDER.equals(c.getEquCategory())).mapToInt(InspectTimeCountDto::getNum).sum();
        item.add(num);
        return item;
    }

    private List<String> getXData(List<EquipmentCategoryDto> equipmentCategoryDtos) {
        // 8大类  + 气瓶 注意数据顺序和要和这个x轴一致
        List<String> names = equipmentCategoryDtos.stream().map(EquipmentCategoryDto::getName).collect(Collectors.toList());
        names.add("气瓶");
        return names;
    }

    private List<BizTypeEnum> getBizTypeList() {
        return Arrays.asList(BizTypeEnum.FIRST_INSPECTION, BizTypeEnum.SUPERVISE, BizTypeEnum.DETECTION);
    }

    private List<Map<String, Object>> getLegendData(List<BizTypeEnum> bizTypeEnums) {
       return bizTypeEnums.stream().map(b->{
            Map<String, Object> item = new HashMap<>();
            item.put("dataKey", b.getCode());
            item.put("value", b.getName());
            return item;
        }).collect(Collectors.toList());
    }

    private void setDefaultFilter(DPFilterParamDto dpFilterParamDto) {
        if (StringUtils.isEmpty(dpFilterParamDto.getBeginDate())) {
            dpFilterParamDto.setBeginDate(DateUtil.lastMonth().toDateStr());
        }
        if (StringUtils.isEmpty(dpFilterParamDto.getEndDate())) {
            dpFilterParamDto.setEndDate(DateUtil.today());
        }
    }

    public Map<String, Object> inspectTimeCount(DPFilterParamDto dpFilterParamDto) {
        Map<String, Object> returnMap = new HashMap<>();
        LocalDate today = LocalDate.now();
        List xDataList = new ArrayList();
        List<Integer> yDataList = new ArrayList();
        DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        for (int i = 2; i >= 0; i--) {
            LocalDate firstDayOfPrevMonth = today.minusMonths(i).with(TemporalAdjusters.firstDayOfMonth());
            LocalDate lastDayOfPrevMonth = today.minusMonths(i).with(TemporalAdjusters.lastDayOfMonth());
            dpFilterParamDto.setBeginDate(LocalDateTime.of(firstDayOfPrevMonth, java.time.LocalTime.MIN).format(sdf));
            dpFilterParamDto.setEndDate(LocalDateTime.of(lastDayOfPrevMonth, java.time.LocalTime.MAX).format(sdf));
            Integer inspectTimeCount = inspectionApplicationEquipMapper.inspectTimeCount(dpFilterParamDto);
            xDataList.add(firstDayOfPrevMonth.getMonthValue()+"月");
            yDataList.add(null == inspectTimeCount ? 0 : inspectTimeCount);
        }
        returnMap.put("xData",xDataList);
        returnMap.put("yData",yDataList);
        return returnMap;
    }
}
