package com.sict.data.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sict.data.dto.*;
import com.sict.data.mapper.DataPlatMapper;
import com.sict.data.model.DataPlat;
import com.sict.data.service.IDataPlatService;
import com.sun.xml.internal.bind.v2.TODO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.lang.reflect.*;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @description 服务实现类
 *
 * @author Jxy
 * @date 2019-10-16
 */
@Slf4j
@AllArgsConstructor
@Service("dataPlatService")
public class DataPlatServiceImpl extends ServiceImpl<DataPlatMapper, DataPlat> implements IDataPlatService {

    private final DataPlatMapper dataPlatMapper;

    /**
     * 获取各医联体下筛查人数排行榜（取前30个医联体） 实现
     * @author Jxy
     */
    @Cacheable(cacheNames = {"getScreeningRank"})
    @Override
    public List<HospScreeningDTO> getScreeningRank() {
    	System.out.println("没有缓存"+new Date().getTime());
        List<HospScreeningDTO> dtoList = dataPlatMapper.getHospScreeningRank();
        return dtoList.stream().limit(30).collect(Collectors.toList());
    }

    /**
     * 获取血清检测人次统计结果（省份） 实现
     * @author Jxy
     */
    @Cacheable(cacheNames = {"getSerumStatistics"})
    @Override
    public SerumDTO getSerumStatistics() {
        List<ProvinceSerumDTO> dtoList = dataPlatMapper.getProvinceSerumStatistics();
        SerumDTO dto = new SerumDTO();
        // 各项结果统计
        this.calculateStatistical(dtoList, ProvinceSerumDTO.class, dto);
        dto.setDtoList(dtoList);
        return dto;
    }

    /**
     * 获取胃镜检查人次统计结果（省份） 实现
     * @author Jxy
     */
    @Override
    @Cacheable(cacheNames = {"getGastroscopyStatistics"})
    public GastroscopyDTO getGastroscopyStatistics() {
        List<ProvinceGastroscopyDTO> dtoList = dataPlatMapper.getProvinceGastroscopyStatistics();
        GastroscopyDTO dto = new GastroscopyDTO();
        // 各项结果统计
        this.calculateStatistical(dtoList, ProvinceGastroscopyDTO.class, dto);
        dto.setDtoList(dtoList);
        return dto;
    }

    /**
     * 获取筛查人次统计结果（省份） 实现
     * @author Jxy
     */
    @Cacheable(cacheNames = {"getScreeningStatistics"})
    @Override
    public ScreeningDTO getScreeningStatistics() {
        List<ProvinceScreeningDTO> dtoList = dataPlatMapper.getProvinceScreeningStatistics();
        ScreeningDTO dto = new ScreeningDTO();
        dto.setTotal(dtoList.stream().mapToInt(ProvinceScreeningDTO::getProvinceScreeningTotal).sum());
        dto.setDtoList(dtoList);
        return dto;
    }

    /**
     * 获取胃镜精查最终诊断异常统计结果 实现
     * @author Jxy
     */
    @Cacheable(cacheNames = {"getGastroscopyDetailResultStatistics"})
    @Override
    public GastroscopyResultDTO getGastroscopyDetailResultStatistics() {
        List<ProvinceGastroscopyResultDTO> dtoList = dataPlatMapper.getProvinceGastroscopyResult();
        GastroscopyResultDTO dto = new GastroscopyResultDTO();
        // 各项结果统计
        this.calculateStatistical(dtoList, ProvinceGastroscopyResultDTO.class, dto);
        dto.setDtoList(dtoList);
        return dto;
    }

    /**
     * 获取患病风险等级评估统计 实现
     * @author Jxy
     */
    @Cacheable(cacheNames = {"getRiskAssessStatistics"})
    @Override
    public RiskAssessDTO getRiskAssessStatistics() {
        return dataPlatMapper.getRiskAssessStatistics();
    }

    /**
     * 获取胃镜精查统计结果 实现
     * @author Jxy
     */
    @Cacheable(cacheNames = {"getGastroscopyDetailStatistics"})
    @Override
    public GastroscopyDetailDTO getGastroscopyDetailStatistics() {
        return dataPlatMapper.getGastroscopyDetailStatistics();
    }

    /**
     * 获取医院相关统计（申请数、认证数、开展筛查数） 实现
     * @author Jxy
     */
    @Cacheable(cacheNames = {"getHospStatistics"})
    @Override
    public HospStatisticsDTO getHospStatistics() {
        HospStatisticsDTO dto = dataPlatMapper.getHospStatistics();
        List<HospScreeningDTO> dtoList = dataPlatMapper.getHospScreeningRank();
        if (CollectionUtil.isEmpty(dtoList)) {
            dto.setScreeningHosp(0);
        } else {
            dto.setScreeningHosp(dtoList.size());
        }
        return dto;
    }

    /**
     * 获取综合统计结果 实现
     * @author Jxy
     */
    @Cacheable(cacheNames = {"getComplexStatistics"})
    @Override
    public ComplexResultDTO getComplexStatistics() {
        ComplexResultDTO dto = new ComplexResultDTO();
        // 血检总人次、igg检测阳性人次
        SerumDTO serumDTO = this.getSerumStatistics();
        dto.setSerumActualTotal(serumDTO.getSerumTestActual());
        dto.setIggPositive(serumDTO.getIggPositive());
        // 应精查人次、实际精查人次
        GastroscopyDetailDTO detailDTO = this.getGastroscopyDetailStatistics();
        dto.setGastroscopyDetailTotal(detailDTO.getTotal());
        dto.setGastroscopyDetailActual(detailDTO.getActual());
        // 各项病变结果
        GastroscopyResultDTO resultDTO = this.getGastroscopyDetailResultStatistics();
        dto.setHighEsophagusTumor(resultDTO.getHighEsophagusTumor());
        dto.setEarlyEsophagealCancer(resultDTO.getEarlyEsophagealCancer());
        dto.setEarlyGastricCancer(resultDTO.getEarlyGastricCancer());
        dto.setAtrophicGastritis(resultDTO.getAtrophicGastritis());
        dto.setStomachUlcer(resultDTO.getStomachUlcer());
        dto.setGastricPolyp(resultDTO.getGastricPolyp());
        // 申请医院、认证医院、开展筛查医院
        HospStatisticsDTO hospDTO = this.getHospStatistics();
        dto.setApplyHosp(hospDTO.getApplyHosp());
        dto.setCertifiedHosp(hospDTO.getCertifiedHosp());
        dto.setScreeningHosp(hospDTO.getScreeningHosp());
        // 筛查统计
        ScreeningDTO screeningDTO = this.getScreeningStatistics();
        dto.setScreeningTotal(screeningDTO.getTotal());
        return dto;
    }

    /**
     * 统计变量求和  要求：T，V中相应的需统计的参数名必须相同
     *
     * @author Jxy
     * @date 10:57 2019/10/22
     * @param tList 统计变量对象集合 非空
     * @param clazz 统计变量Class对象 非空
     * @param v 统计结果对象 非空
     */
    private <T, V> void calculateStatistical(@NotNull List<T> tList, @NotNull Class<T> clazz, @NotNull V v) {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            String fieldName = field.getName();
            String firstLetter = fieldName.substring(0, 1);
            String newFieldName = fieldName.replaceFirst(firstLetter, firstLetter.toUpperCase());
            if (ObjectUtil.equal(field.getType(), Integer.class)) {
                int sum = tList.stream().mapToInt(value -> {
                    try {
                        return (int) clazz.getMethod("get" + newFieldName).invoke(value);
                    } catch (Exception e) {
                        log.error("计算求和出现错误。错误信息：【{}】，错误详情：【{}】", e.toString(), e.getMessage());
                        return 0;
                    }
                }).sum();
                try {
                    v.getClass().getMethod("set" + newFieldName, Integer.class).invoke(v, sum);
                } catch (Exception e) {
                    log.error("设置求和数据出现错误。错误信息：【{}】，错误详情：【{}】", e.toString(), e.getMessage());
                }
            }
        }
    }

}
