package com.diagbot.aggregate;

import com.diagbot.dto.AverageStatisticsDTO;
import com.diagbot.facade.FilterFacade;
import com.diagbot.facade.HomePageFacade;
import com.diagbot.facade.QcresultInfoFacade;
import com.diagbot.util.BeanUtil;
import com.diagbot.util.DateUtil;
import com.diagbot.util.EntityUtil;
import com.diagbot.util.ListUtil;
import com.diagbot.vo.FilterVO;
import com.google.common.collect.Lists;
import io.github.lvyahui8.spring.annotation.DataConsumer;
import io.github.lvyahui8.spring.annotation.DataProvider;
import io.github.lvyahui8.spring.annotation.InvokeParameter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description:平均值相关统计
 * @Author:zhaops
 * @time: 2020/4/23 14:11
 */
@Component
public class AverageStatisticsAggregate {
    @Autowired
    private HomePageFacade homePageFacade;
    @Autowired
    private QcresultInfoFacade qcresultInfoFacade;
    @Autowired
    private FilterFacade filterFacade;

    @DataProvider("setAllAverage")
    public Map<String, Object> setAllResult(
            @InvokeParameter("filterVO") FilterVO filterVO,
            @DataConsumer("getAverageDayNum") List<AverageStatisticsDTO> averageDayNumList,
            @DataConsumer("getAverageFee") List<AverageStatisticsDTO> averageFeeList,
            @DataConsumer("getAverageScore") List<AverageStatisticsDTO> averageScoreList) {
        Map<String, Object> retMap = new LinkedHashMap<>();
        retMap.put("平均住院日", Lists.newLinkedList());
        retMap.put("平均住院费用", Lists.newLinkedList());
        retMap.put("各科室质控平均分", Lists.newLinkedList());
        if (ListUtil.isNotEmpty(averageDayNumList)) {
            retMap.put("平均住院日", averageDayNumList);
        }
        if (ListUtil.isNotEmpty(averageFeeList)) {
            retMap.put("平均住院费用", averageFeeList);
        }
        if (ListUtil.isNotEmpty(averageScoreList)) {
            retMap.put("各科室质控平均分", averageScoreList);
        }
        return retMap;
    }

    /**
     * 平均住院天数
     *
     * @param filterVO
     * @return
     */
    @DataProvider("getAverageDayNum")
    public List<AverageStatisticsDTO> getAverageDayNum(@InvokeParameter("filterVO") FilterVO filterVO) {
        Integer limitCount = filterVO.getLimitCount();
        List<AverageStatisticsDTO> retAverageDayNumList = Lists.newLinkedList();
        //本月、本年
        List<AverageStatisticsDTO> averageDayNumList = homePageFacade.getAverageDayNum(filterVO);
        Map<String, Double> averageMap
                = EntityUtil.makeMapWithKeyValue(averageDayNumList, "name", "averageValue");

        //上月、去年
        String startDate = filterFacade.getLastStartDateStr(filterVO.getType());
        String endDate = filterFacade.getLastEndDateStr(filterVO.getType());
        filterVO.setStartDate(startDate);
        filterVO.setEndDate(endDate);
        List<AverageStatisticsDTO> lastAverageDayNumList = homePageFacade.getAverageDayNum(filterVO);
        Map<String, Double> lastMap
                = EntityUtil.makeMapWithKeyValue(lastAverageDayNumList, "name", "averageValue");

        //去年本月
        if (filterVO.getType().equals(1)) {
            Date date = new Date();
            String year = DateUtil.getYear(date);
            startDate = filterFacade.getStartDateStr(filterVO.getType(), Integer.valueOf(year) - 1);
            endDate = filterFacade.getEndDateStr(filterVO.getType(), Integer.valueOf(year) - 1);
            filterVO.setStartDate(startDate);
            filterVO.setEndDate(endDate);
        }
        //按年统计，同比环比相同
        List<AverageStatisticsDTO> lastYearAverageDayNumList = homePageFacade.getAverageDayNum(filterVO);
        Map<String, Double> lastYearMap
                = EntityUtil.makeMapWithKeyValue(lastYearAverageDayNumList, "name", "averageValue");

        //获取所有出现的科室
        List<String> nameList = Lists.newLinkedList();
        nameList.addAll(averageMap.keySet());
        nameList.addAll(lastMap.keySet());
        nameList.addAll(lastYearMap.keySet());
        nameList = nameList
                .stream()
                .distinct()
                .collect(Collectors.toList());

        for (String name : nameList) {
            AverageStatisticsDTO item = new AverageStatisticsDTO();
            item.setName(name);
            if (averageMap.containsKey(name)) {
                item.setAverageValue(averageMap.get(name));
            }
            if (lastMap.containsKey(name)) {
                item.setLastAverageValue(lastMap.get(name));
            }
            if (lastYearMap.containsKey(name)) {
                item.setLastYearAverageValue(lastYearMap.get(name));
            }
            retAverageDayNumList.add(item);
        }

        //排序
        Collections.sort(retAverageDayNumList, new Comparator<AverageStatisticsDTO>() {
            @Override
            public int compare(AverageStatisticsDTO o1, AverageStatisticsDTO o2) {
                Double value1 = o1.getAverageValue();
                Double lastValue1 = o1.getLastAverageValue();
                Double lastYearValue1 = o1.getLastYearAverageValue();
                Double value2 = o2.getAverageValue();
                Double lastValue2 = o2.getLastAverageValue();
                Double lastYearValue2 = o2.getLastYearAverageValue();
                Integer count1 = 0;
                count1 += Double.compare(value1, 0) == 0 ? 0 : 1;
                count1 += Double.compare(lastValue1, 0) == 0 ? 0 : 1;
                count1 += Double.compare(lastYearValue1, 0) == 0 ? 0 : 1;
                Integer count2 = 0;
                count2 += Double.compare(value2, 0) == 0 ? 0 : 1;
                count2 += Double.compare(lastValue2, 0) == 0 ? 0 : 1;
                count2 += Double.compare(lastYearValue2, 0) == 0 ? 0 : 1;
                return (count1 > count2) ? -1 : ((count1 < count2) ? 1 : 0);
            }
        });

        if (retAverageDayNumList.size() > limitCount) {
            retAverageDayNumList = retAverageDayNumList.subList(0, limitCount);
        }
        return retAverageDayNumList;
    }

    /**
     * 平均住院费用
     *
     * @param filterVO
     * @return
     */
    @DataProvider("getAverageFee")
    public List<AverageStatisticsDTO> getAverageFee(@InvokeParameter("filterVO") FilterVO filterVO) {
        Integer limitCount = filterVO.getLimitCount();
        List<AverageStatisticsDTO> retAverageFeeList = Lists.newLinkedList();
        //本月、本年
        List<AverageStatisticsDTO> averageFeeList = homePageFacade.getAverageFee(filterVO);
        Map<String, Double> averageMap
                = EntityUtil.makeMapWithKeyValue(averageFeeList, "name", "averageValue");

        //上月、去年
        String startDate = filterFacade.getLastStartDateStr(filterVO.getType());
        String endDate = filterFacade.getLastEndDateStr(filterVO.getType());
        filterVO.setStartDate(startDate);
        filterVO.setEndDate(endDate);
        List<AverageStatisticsDTO> lastAverageFeeList = homePageFacade.getAverageFee(filterVO);
        Map<String, Double> lastMap
                = EntityUtil.makeMapWithKeyValue(lastAverageFeeList, "name", "averageValue");

        //去年本月
        if (filterVO.getType().equals(1)) {
            Date date = new Date();
            String year = DateUtil.getYear(date);
            startDate = filterFacade.getStartDateStr(filterVO.getType(), Integer.valueOf(year) - 1);
            endDate = filterFacade.getEndDateStr(filterVO.getType(), Integer.valueOf(year) - 1);
            filterVO.setStartDate(startDate);
            filterVO.setEndDate(endDate);
        }
        //按年统计，同比环比相同
        List<AverageStatisticsDTO> lastYearAverageFeeList = homePageFacade.getAverageFee(filterVO);
        Map<String, Double> lastYearMap
                = EntityUtil.makeMapWithKeyValue(lastYearAverageFeeList, "name", "averageValue");

        //获取所有出现的科室
        List<String> nameList = Lists.newLinkedList();
        nameList.addAll(averageMap.keySet());
        nameList.addAll(lastMap.keySet());
        nameList.addAll(lastYearMap.keySet());
        nameList = nameList
                .stream()
                .distinct()
                .collect(Collectors.toList());

        for (String name : nameList) {
            AverageStatisticsDTO item = new AverageStatisticsDTO();
            item.setName(name);
            if (averageMap.containsKey(name)) {
                item.setAverageValue(averageMap.get(name));
            }
            if (lastMap.containsKey(name)) {
                item.setLastAverageValue(lastMap.get(name));
            }
            if (lastYearMap.containsKey(name)) {
                item.setLastYearAverageValue(lastYearMap.get(name));
            }
            retAverageFeeList.add(item);
        }

        //排序
        Collections.sort(retAverageFeeList, new Comparator<AverageStatisticsDTO>() {
            @Override
            public int compare(AverageStatisticsDTO o1, AverageStatisticsDTO o2) {
                Double value1 = o1.getAverageValue();
                Double lastValue1 = o1.getLastAverageValue();
                Double lastYearValue1 = o1.getLastYearAverageValue();
                Double value2 = o2.getAverageValue();
                Double lastValue2 = o2.getLastAverageValue();
                Double lastYearValue2 = o2.getLastYearAverageValue();
                Integer count1 = 0;
                count1 += Double.compare(value1, 0) == 0 ? 0 : 1;
                count1 += Double.compare(lastValue1, 0) == 0 ? 0 : 1;
                count1 += Double.compare(lastYearValue1, 0) == 0 ? 0 : 1;
                Integer count2 = 0;
                count2 += Double.compare(value2, 0) == 0 ? 0 : 1;
                count2 += Double.compare(lastValue2, 0) == 0 ? 0 : 1;
                count2 += Double.compare(lastYearValue2, 0) == 0 ? 0 : 1;
                return (count1 > count2) ? -1 : ((count1 < count2) ? 1 : 0);
            }
        });

        if (retAverageFeeList.size() > limitCount) {
            retAverageFeeList = retAverageFeeList.subList(0, limitCount);
        }
        return retAverageFeeList;
    }

    /**
     * 质控平均分按科室统计
     *
     * @param filterVO
     * @return
     */
    @DataProvider("getAverageScore")
    public List<AverageStatisticsDTO> getAverageScore(@InvokeParameter("filterVO") FilterVO filterVO) {
        List<AverageStatisticsDTO> retAverageScoreList = Lists.newLinkedList();
        List<AverageStatisticsDTO> averageScoreList = qcresultInfoFacade.getAverageScore(filterVO);
        Integer limitCount = filterVO.getLimitCount();
        //质控平均分
        if (ListUtil.isNotEmpty(averageScoreList)) {
            retAverageScoreList = getLimitAverageList(averageScoreList, limitCount);
        }
        return retAverageScoreList;
    }

    /**
     * 根据限制数量重组统计结果
     *
     * @param averageList
     * @param limitCount
     * @return
     */
    public List<AverageStatisticsDTO> getLimitAverageList(List<AverageStatisticsDTO> averageList, Integer limitCount) {
        List<AverageStatisticsDTO> retAverageList = Lists.newLinkedList();
        if (averageList.size() <= limitCount) {
            retAverageList = BeanUtil.listCopyTo(averageList, AverageStatisticsDTO.class);
        } else {
            retAverageList = averageList.subList(0, limitCount - 2);
            List<AverageStatisticsDTO> otherList = averageList.subList(limitCount - 2, averageList.size());
            Double totleValue = otherList
                    .stream()
                    .map(i -> BigDecimal.valueOf(i.getTotleValue()))
                    .reduce(BigDecimal.ZERO, BigDecimal::add).doubleValue();
            Double sameTotleValue = otherList
                    .stream()
                    .map(i -> BigDecimal.valueOf(i.getSameTotleValue()))
                    .reduce(BigDecimal.ZERO, BigDecimal::add).doubleValue();
            Integer num = otherList
                    .stream()
                    .map(AverageStatisticsDTO::getNum)
                    .reduce(0, Integer::sum);
            Integer sameNum = otherList
                    .stream()
                    .map(AverageStatisticsDTO::getSameNum)
                    .reduce(0, Integer::sum);
            Double averageValue = BigDecimal.valueOf(totleValue)
                    .divide(BigDecimal.valueOf(num), 2, RoundingMode.HALF_UP)
                    .doubleValue();
            Double lastYearAverageValue = 0d;
            if(0 != sameNum){
                 lastYearAverageValue = BigDecimal.valueOf(sameTotleValue)
                        .divide(BigDecimal.valueOf(sameNum), 2, RoundingMode.HALF_UP)
                        .doubleValue();
            }


            AverageStatisticsDTO retAverageStatistics = new AverageStatisticsDTO();
            retAverageStatistics.setName("其他");
            retAverageStatistics.setNum(num);
            retAverageStatistics.setSameNum(sameNum);
            retAverageStatistics.setSameTotleValue(sameTotleValue);
            retAverageStatistics.setLastYearAverageValue(lastYearAverageValue);
            retAverageStatistics.setAverageValue(averageValue);
            retAverageStatistics.setTotleValue(totleValue);
            retAverageList.add(retAverageStatistics);
        }
        return retAverageList;
    }
}
