package com.diagbot.facade;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.diagbot.dto.AlgorithmDTO;
import com.diagbot.entity.QcresultDetail;
import com.diagbot.exception.CommonErrorCode;
import com.diagbot.exception.CommonException;
import com.diagbot.util.BeanUtil;
import com.diagbot.util.BigDecimalUtil;
import com.diagbot.util.ListUtil;
import com.diagbot.util.StringUtil;
import com.diagbot.vo.AlgorithmVO;
import com.diagbot.vo.MedQcresultCasesVO;
import com.diagbot.vo.QcResultAlgVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 评分算法
 * @author: gaodm
 * @time: 2020/4/14 9:52
 */
@Component
public class AlgorithmFacade {
    private final static List<Integer> types = Arrays.asList(0, 1, 2, 3,4);

    @Autowired
    private SysHospitalSetFacade sysHospitalSetFacade;
    @Autowired
    private QcresultDetailFacade qcresultDetailFacade;

    /**
     * 获取评分结果和等级
     *
     * @param algorithmVO 操作条目的所有信息
     * @return 评分结果和等级
     */
    public AlgorithmDTO getAlgorithmRes(AlgorithmVO algorithmVO) {
        AlgorithmDTO algorithmDTO = new AlgorithmDTO();
        BigDecimal score = this.getScore(algorithmVO);
        algorithmDTO.setScore(score);
        algorithmDTO.setLevel(this.getLevel(score));
        return algorithmDTO;
    }

    /**
     * 评结果分数
     *
     * @param algorithmVO 操作条目的所有信息
     * @return 评结果分数
     */
    private BigDecimal getScore(AlgorithmVO algorithmVO) {
        if (!types.contains(algorithmVO.getType())) {
            throw new CommonException(CommonErrorCode.PARAM_IS_ERROR, "操作类型只有0,1,2,3!");
        }
        //处理数据
        dataDeal(algorithmVO);

        BigDecimal res = BigDecimal.ZERO;
        //统一为长兴的算法
        res = getScoreForCx(algorithmVO);
        return res;
    }

    /**
     * 评结果分数(长兴)
     *
     * @param algorithmVO 操作条目的所有信息
     * @return 评结果分数
     */
    private BigDecimal getScoreForCx(AlgorithmVO algorithmVO) {
        List<QcResultAlgVO> qcResultAlgHomePage = new ArrayList<>();
        List<QcResultAlgVO> qcResultAlgHomePageExt = new ArrayList<>();
        for (QcResultAlgVO qcResultAlgVO : algorithmVO.getQcResultAlgVOList()) {
            //首页的情况
            if (qcResultAlgVO.getCasesId().equals(243L)) {
                qcResultAlgHomePage.add(qcResultAlgVO);
            } else {
                //非首页
                qcResultAlgHomePageExt.add(qcResultAlgVO);
            }
        }
        List<MedQcresultCasesVO> medQcresultCasesVOList = new ArrayList<>();
        //病案首页
        AlgorithmVO homePage = new AlgorithmVO();
        BeanUtil.copyProperties(algorithmVO, homePage);
        homePage.setQcResultAlgVOList(qcResultAlgHomePage);
        homePage.setIsHomePage(true);
        BigDecimal homePageRes = cal(homePage);
        String level = getHomePageLevel(homePageRes);
        MedQcresultCasesVO medQcresultCasesVOHp = new MedQcresultCasesVO();
        medQcresultCasesVOHp.setHospitalId(algorithmVO.getHospitalId());
        medQcresultCasesVOHp.setBehospitalCode(algorithmVO.getBehospitalCode());
        medQcresultCasesVOHp.setCasesId(243L);
        medQcresultCasesVOHp.setScoreRes(homePageRes);
        medQcresultCasesVOHp.setLevel(level);
        medQcresultCasesVOList.add(medQcresultCasesVOHp);
        //病案首页以外
        AlgorithmVO homePageExt = new AlgorithmVO();
        BeanUtil.copyProperties(algorithmVO, homePageExt);
        homePageExt.setQcResultAlgVOList(qcResultAlgHomePageExt);
        BigDecimal homePageExtRes = cal(homePageExt);
        MedQcresultCasesVO medQcresultCasesVOHpExt = new MedQcresultCasesVO();
        medQcresultCasesVOHpExt.setHospitalId(algorithmVO.getHospitalId());
        medQcresultCasesVOHpExt.setBehospitalCode(algorithmVO.getBehospitalCode());
        medQcresultCasesVOHpExt.setCasesId(0L);
        medQcresultCasesVOHpExt.setScoreRes(homePageExtRes);
        medQcresultCasesVOHpExt.setLevel("");
        medQcresultCasesVOList.add(medQcresultCasesVOHpExt);
        algorithmVO.setMedQcresultCasesVOList(medQcresultCasesVOList);
        //计算分数
        BigDecimal res = homePageRes
                .add(homePageExtRes)
                .multiply(new BigDecimal(100))
                .divide(new BigDecimal(120), 1, RoundingMode.HALF_UP);
        // 判断是否是百分制
        if (sysHospitalSetFacade.getScoreType(algorithmVO.getHospitalId()).equals("1")
                ||(algorithmVO.getHospitalId().intValue() == 1
                && StringUtil.isNotBlank(algorithmVO.getIsPlacefile())
                && algorithmVO.getIsPlacefile().equals("0"))) {
            res = cal(algorithmVO);
        }
        return res;
    }

    /**
     * 根据分数评定等级（病案首页）
     *
     * @param score 评分分数
     * @return 等级
     */
    private String getHomePageLevel(BigDecimal score) {
        String level = "不合格";
        //得分≥18分为甲级
        if (BigDecimalUtil.ge(score, new BigDecimal(18))) {
            level = "合格";
        }
        return level;
    }

    /**
     * 根据分数评定等级
     *
     * @param score 评分分数
     * @return 等级
     */
    private String getLevel(BigDecimal score) {
        String level = "甲";
        //得分≥90分为甲级
        if (BigDecimalUtil.ge(score, new BigDecimal(90))) {
            level = "甲";
        }
        //得分<90分且得分≥80分为乙级
        if (BigDecimalUtil.lt(score, new BigDecimal(90))
                && BigDecimalUtil.ge(score, new BigDecimal(80))) {
            level = "乙";
        }
        //得分<80分为丙级
        if (BigDecimalUtil.lt(score, new BigDecimal(80))) {
            level = "丙";
        }

        return level;
    }

    /**
     * 处理数据
     *
     * @param algorithmVO 操作条目的所有信息
     */
    private void dataDeal(AlgorithmVO algorithmVO) {
        List<QcResultAlgVO> qcResultAlgVOList = algorithmVO.getQcResultAlgVOList();
        //新增
        if (algorithmVO.getType().equals(1)) {
            if (null == algorithmVO.getOptResultAlgVO()) {
                throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "新增操作条目不能为空！");
            }
            //验证和操作数据
            if (ListUtil.isNotEmpty(qcResultAlgVOList)) {
                for (QcResultAlgVO qcResultAlgVO : qcResultAlgVOList) {
                    if (qcResultAlgVO.getCasesId().equals(algorithmVO.getOptResultAlgVO().getCasesId())
                            && qcResultAlgVO.getCasesEntryId().equals(algorithmVO.getOptResultAlgVO().getCasesEntryId())) {
                        throw new CommonException(CommonErrorCode.PARAM_IS_ERROR, "不能重复加入已经评分的条目");
                    } else {
                        if (algorithmVO.getOptResultAlgVO().getCasesId().equals(qcResultAlgVO.getCasesId())) {
                            algorithmVO.getOptResultAlgVO().setCasesScore(qcResultAlgVO.getCasesScore());
                        }
                    }
                }
                qcResultAlgVOList.add(algorithmVO.getOptResultAlgVO());
            }
            if(ListUtil.isEmpty(qcResultAlgVOList)){
                qcResultAlgVOList = new ArrayList<>();
                qcResultAlgVOList.add(algorithmVO.getOptResultAlgVO());
                algorithmVO.setQcResultAlgVOList(qcResultAlgVOList);
            }
        }
        //删除
        else if (algorithmVO.getType().equals(2)||(algorithmVO.getType().equals(4)&&0==algorithmVO.getDelStatus())) {
            if (null == algorithmVO.getOptResultAlgVO()) {
                throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "删除操作条目不能为空！");
            }
            //操作数据
            if (ListUtil.isNotEmpty(qcResultAlgVOList)) {
                Boolean hasData = false;
                Long optId = algorithmVO.getOptResultAlgVO().getId(); // 操作id
                for (QcResultAlgVO qcResultAlgVO : qcResultAlgVOList) {
                    if (qcResultAlgVO.getId().equals(optId)) {
                        qcResultAlgVOList.remove(qcResultAlgVO);
                        hasData = true;
                        break;
                    }
                }
                if (!hasData) {
                    throw new CommonException(CommonErrorCode.PARAM_IS_ERROR, "删除的条目不存在！");
                }
            }
        }
        //恢复
        else if (algorithmVO.getType().equals(4)&&1==algorithmVO.getDelStatus()) {
            if (null == algorithmVO.getOptResultAlgVO()) {
                throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "恢复操作条目不能为空！");
            }
            //操作数据
            Boolean hasData = false;
            Long optId = algorithmVO.getOptResultAlgVO().getId(); // 操作id
            QcresultDetail qcresultDetail = qcresultDetailFacade.getOne(new QueryWrapper<QcresultDetail>()
                    .eq("id",optId));
            if(qcresultDetail!=null)
            {
                QcResultAlgVO qcResultAlgVO = new QcResultAlgVO();
                qcResultAlgVO.setScore(qcresultDetail.getScore());
                qcResultAlgVO.setId(qcresultDetail.getId());
                qcResultAlgVO.setCasesEntryId(qcresultDetail.getCasesEntryId());
                qcResultAlgVO.setCasesId(qcresultDetail.getCasesId());
                qcResultAlgVO.setMsg(qcresultDetail.getMsg());
                qcResultAlgVO.setIsReject(qcresultDetail.getIsReject());
                qcResultAlgVO.setCasesScore(qcresultDetail.getCasesScore());
                if (ListUtil.isNotEmpty(qcResultAlgVOList)) {
                    qcResultAlgVOList.add(qcResultAlgVO);
                }else{
                    qcResultAlgVOList = new ArrayList<>();
                    qcResultAlgVOList.add(qcResultAlgVO);
                    algorithmVO.setQcResultAlgVOList(qcResultAlgVOList);
                }
                hasData = true;
            }
                if (!hasData) {
                    throw new CommonException(CommonErrorCode.PARAM_IS_ERROR, "恢复的条目不存在！");
                }
        }

        //修改
        else if (algorithmVO.getType().equals(3)) {
            if (null == algorithmVO.getOptResultAlgVO()) {
                throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "修改操作条目不能为空！");
            }
            //操作数据
            if (ListUtil.isNotEmpty(qcResultAlgVOList)) {
                Boolean hasData = false;
                for (QcResultAlgVO qcResultAlgVO : qcResultAlgVOList) {
                    if (qcResultAlgVO.getId().equals(algorithmVO.getOptResultAlgVO().getId())) {
                        qcResultAlgVOList.remove(qcResultAlgVO);
                        qcResultAlgVOList.add(algorithmVO.getOptResultAlgVO());
                        hasData = true;
                        break;
                    }
                }
                if (!hasData) {
                    throw new CommonException(CommonErrorCode.PARAM_IS_ERROR, "修改的条目不存在！");
                }
            }
        }
    }

    /**
     * 计算分数
     *
     * @param algorithmVO 操作条目的所有信息
     * @return 评分分数
     */
    private BigDecimal cal(AlgorithmVO algorithmVO) {
        BigDecimal res = new BigDecimal(100);
        //统一为长兴的算法
        if (algorithmVO.getIsHomePage().equals(true)) {
            res = new BigDecimal(20);
        }
        //模块总分
        Map<Long, BigDecimal> casesMap = new HashMap<>();
        //单票否决计分
        BigDecimal rejectScore = BigDecimal.ZERO;
        //模块计分
        Map<Long, BigDecimal> casesScoreMap = new HashMap<>();

        List<QcResultAlgVO> qcResultAlgVOList = algorithmVO.getQcResultAlgVOList();
        if (ListUtil.isNotEmpty(qcResultAlgVOList)) {
            for (QcResultAlgVO qcResultAlgVO : qcResultAlgVOList) {
                if (!casesMap.containsKey(qcResultAlgVO.getCasesId())) {
                    casesMap.put(qcResultAlgVO.getCasesId(), qcResultAlgVO.getCasesScore());
                }
                if (!casesScoreMap.containsKey(qcResultAlgVO.getCasesId())) {
                    casesScoreMap.put(qcResultAlgVO.getCasesId(), BigDecimal.ZERO);
                }
                //单票否决计分
                if (qcResultAlgVO.getIsReject().equals(1)) {
                    rejectScore = rejectScore.add(qcResultAlgVO.getScore());
                } else {
                    //非单票否决计分
                    if (casesScoreMap.containsKey(qcResultAlgVO.getCasesId())) {
                        BigDecimal casesScore = casesScoreMap.get(qcResultAlgVO.getCasesId());
                        casesScore = casesScore.add(qcResultAlgVO.getScore());
                        casesScoreMap.put(qcResultAlgVO.getCasesId(), casesScore);
                    }
                }
            }

            //结果先减去单票否决计分总和
            res = res.subtract(rejectScore);
            //结果小于0按0计算
            if (BigDecimalUtil.lt(res, BigDecimal.ZERO)) {
                return BigDecimal.ZERO;
            } else {
                //模块计分
                for (Map.Entry<Long, BigDecimal> casesScore : casesScoreMap.entrySet()) {
                    BigDecimal allSccore = casesMap.get(casesScore.getKey());
                    if (BigDecimalUtil.le(allSccore, casesScore.getValue())) {
                        //模块标准分小于等于模块减分总和就用模块标准分
                        res = res.subtract(allSccore);
                    } else {
                        //模块标准分大于模块减分总和就用模块减分总和
                        res = res.subtract(casesScore.getValue());
                    }
                }
            }
            //结果小于0按0计算
            if (BigDecimalUtil.lt(res, BigDecimal.ZERO)) {
                res = BigDecimal.ZERO;
            }
        }
        return res;
    }

    public static void main(String[] args) {
        AlgorithmFacade algorithmFacade = new AlgorithmFacade();
        System.out.println("100:" + algorithmFacade.getLevel(new BigDecimal(100)));
        System.out.println("95:" + algorithmFacade.getLevel(new BigDecimal(95)));
        System.out.println("90.1:" + algorithmFacade.getLevel(new BigDecimal(90.1)));
        System.out.println("90:" + algorithmFacade.getLevel(new BigDecimal(90)));
        System.out.println("85:" + algorithmFacade.getLevel(new BigDecimal(85)));
        System.out.println("80.1:" + algorithmFacade.getLevel(new BigDecimal(80.1)));
        System.out.println("80:" + algorithmFacade.getLevel(new BigDecimal(80)));
        System.out.println("79.9:" + algorithmFacade.getLevel(new BigDecimal(79.9)));
        System.out.println("60:" + algorithmFacade.getLevel(new BigDecimal(60)));
        System.out.println("0:" + algorithmFacade.getLevel(new BigDecimal(0)));


        System.out.println("18:" + algorithmFacade.getHomePageLevel(new BigDecimal(20)));
        System.out.println("18:" + algorithmFacade.getHomePageLevel(new BigDecimal(18)));
        System.out.println("17.9:" + algorithmFacade.getHomePageLevel(new BigDecimal(17.9)));

        if (BigDecimalUtil.lt(new BigDecimal(-1), BigDecimal.ZERO)) {
            System.out.println(BigDecimal.ZERO);
        }
    }
}
