package org.jeecg.modules.stm.metric.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.stm.metric.entity.MetricStatReport;
import org.jeecg.modules.stm.metric.mapper.MetricStatReportMapper;
import org.jeecg.modules.stm.metric.service.IMetricStatReportService;
import org.springframework.stereotype.Service;

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;

/**
 * @Description: 监测报告
 * @Author: jeecg-boot
 * @Date:   2024-01-04
 * @Version: V1.0
 */
@Service
public class MetricStatReportServiceImpl extends ServiceImpl<MetricStatReportMapper, MetricStatReport> implements IMetricStatReportService {

    @Override
    public List<Map<String,Object>> queryMetricStatByDomain(MetricStatReport metricStatReport) {
        List<Map<String,Object>> data = this.baseMapper.queryMetricStatByDomain(metricStatReport);
        return data;
    }

    @Override
    public List<Map<String,Object>> queryMetricStatByMtricClass(MetricStatReport metricStatReport) {
        List<Map<String,Object>> data = this.baseMapper.queryMetricStatByMtricClass(metricStatReport);
        return data;
    }

    @Override
    public List<Map<String,Object>> queryMetricStatDetail(MetricStatReport metricStatReport) {
        List<Map<String,Object>> data = this.baseMapper.queryMetricStatDetail(metricStatReport);
        return data;
    }

    @Override
    public Map<String, Integer[]> list2Map(List<String> codeList, List<Map<String, Object>> datas) {
        Map<String, Integer[]> riskMap = new LinkedHashMap<>();
        int len = codeList.size();

        // 初始化数组
        Integer[] level0 = new Integer[len];
        Integer[] level1 = new Integer[len];
        Integer[] level2 = new Integer[len];
        Integer[] level3 = new Integer[len];

        // 初始化数组元素为0
        for (int i = 0; i < len; i++) {
            level0[i] = 0;
            level1[i] = 0;
            level2[i] = 0;
            level3[i] = 0;
        }

        // 创建code到索引的映射，提高查找效率
        Map<Integer, Integer> codeIndexMap = new HashMap<>();
        for (int i = 0; i < len; i++) {
            codeIndexMap.put(Integer.parseInt(codeList.get(i)), i);
        }

        // 遍历数据
        for (Map<String, Object> tmpMap : datas) {
            int code = Integer.parseInt(tmpMap.get("code").toString());
            int riskLevel = Optional.ofNullable(tmpMap.get("riskLevel"))
                    .map(Object::toString)
                    .map(Integer::parseInt)
                    .orElse(0);
            int cnt = Integer.parseInt(tmpMap.get("cnt").toString());

            // 查找code对应的索引
            Integer index = codeIndexMap.get(code);
            if (index != null) {
                // 根据风险等级累加到对应数组
                switch (riskLevel) {
                    case 0:
                        level0[index] += cnt;
                        break;
                    case 1:
                        level1[index] += cnt;
                        break;
                    case 2:
                        level2[index] += cnt;
                        break;
                    case 3:
                        level3[index] += cnt;
                        break;
                    default:
                        // 默认情况，可以根据需求处理
                        break;
                }
            } else {
                // 如果code不在codeList中，可以作为"其他"处理
                // 这里需要根据业务需求决定如何处理
            }
        }

        //riskMap.put("其他", level0);
        riskMap.put("正常", level1);
        riskMap.put("预警", level2);
        riskMap.put("干预", level3);

        return riskMap;
    }

    @Override
    public Map<Integer,List<Map<String,Object>>> list2DetailData(List<String> listCode,List<Map<String,Object>> datas,int statMethod) {
        Map<Integer,List<Map<String,Object>>> retMap = new HashMap<>();

        for(int i=0;i<listCode.size();i++) {
            List<Map<String,Object>> cList = new ArrayList<>();
            String dcode = listCode.get(i);
            for(int j=0;j<datas.size();j++) {
                Map<String, Object> data = datas.get(j);
                if(statMethod ==1) {
                    if(data.get("domainCode")==null) continue;
                    String code = data.get("domainCode").toString();
                    if(code.indexOf(dcode)==0){
                        cList.add(data);
                    }
                } else {
                    if(data.get("mtrcClass")==null) continue;
                    int scode = Integer.parseInt(dcode);
                    int code = Integer.parseInt(data.get("mtrcClass").toString());
                    if(code==scode){
                        cList.add(data);
                    }
                }

            }
            retMap.put(Integer.valueOf(dcode),cList);

        }
        return retMap;
    }

    @Override
    public Map<String,Object> list2RiskStat(List<Map<String,Object>> datas,Integer total){
        Map<String,Integer> numMap = new HashMap<>();
        Map<String,Float> percentMap = new HashMap<>();
        Map<String,Object> retMap = new HashMap<>();
        Integer low=0,middle=0,hight=0,other=0;

        for(int i=0;i<datas.size();i++) {
            Map<String,Object> data = datas.get(i);
            int cnt = Integer.parseInt(data.get("cnt").toString());
            int level = data.get("riskLevel")==null?0:Integer.parseInt(data.get("riskLevel").toString());
            if(level==0) other+=cnt ;
            if(level==1) low+=cnt;
            if(level==2) middle+=cnt;
            if(level==3) hight+=cnt;
        }

        total = low + hight + middle;
        retMap.put("total",total);

        numMap.put("low",low);
        numMap.put("middle",middle);
        numMap.put("hight",hight);
        //numMap.put("other",other);
        numMap.put("total",total);
        retMap.put("num",numMap);

        percentMap.put("low",calculate(total,low));
        percentMap.put("middle",calculate(total,middle));
        percentMap.put("hight",calculate(total,hight));
        //percentMap.put("other",calculate(total,other));;
        retMap.put("percent",percentMap);

        return retMap;
    }

    @Override
    public String getOverallDes(List<Map<String,Object>> datas,long currNum,long beforeNum,String durationName) {
        StringBuffer sb = new StringBuffer();
        Map<Integer,Integer> tmpMap = new HashMap<>();
        Map<Integer,String> tmpMapName = new HashMap<>();
        int total = 0;
        for(int i=0;i<datas.size();i++) {
            Map<String, Object> data = datas.get(i);
            Integer code = Integer.parseInt(data.get("code").toString());
            int cnt = Integer.parseInt(data.get("cnt").toString());
            if(tmpMap.get(code)!=null) {
                tmpMap.put(code, (tmpMap.get(code) + cnt));
            } else {
                tmpMap.put(code,cnt);
            }
            tmpMapName.put(code,data.get("name").toString());
            total+=cnt;
        }
        sb.append("本期对"+currNum+"项信息科技风险指标实施了监测");
        if(beforeNum>0){

            long m = currNum-beforeNum;
            if(m>0){
                sb.append("，比上").append(durationName);
                sb.append("新增");
                sb.append(Math.abs(m)).append("个指标");
            } else if(m<0) {
                sb.append("，比上").append(durationName);
                sb.append("减少");
                sb.append(Math.abs(m)).append("个指标");
            } else {
                sb.append("，与上").append(durationName);
                sb.append("统计指标个数相同");
            }
        }
        sb.append("。其中");
        for(Integer code : tmpMap.keySet()) {
            Integer value = tmpMap.get(code);
            sb.append(",").append(tmpMapName.get(code)).append("相关指标").append(value).append("个");
        }
        return sb.toString();
    }

    @Override
    public String getOverallDesOther(Map<String,Object> overallStaData){
        StringBuffer sb = new StringBuffer();
        Map<String,Integer> numMap = (Map<String,Integer>)overallStaData.get("num");
        Map<String,Float> percentMap = (Map<String,Float>)overallStaData.get("percent");
        sb.append("有").append(numMap.get("low")).append("项指标监测结果良好，属于正常状态（绿区）;");
        sb.append(numMap.get("middle")).append("项指标处于预警状态（黄区）;");
        sb.append(numMap.get("hight")).append("项指标处于干预状态（红区）;");
        //sb.append("其它区域指标").append(numMap.get("other")).append("项。");
        sb.append("处于正常状态指标占比").append(percentMap.get("low")).append("%");
        return sb.toString();
    }

    @Override
    public String getDetailDes(List<Map<String,Object>> datas){
        int len = datas.size();
        int low = 0,middle=0,hight=0,other=0;
        for(int i=0;i<len;i++) {
            Map<String, Object> data = datas.get(i);
            int riskLevel = data.get("riskLevel")==null?0:Integer.parseInt(data.get("riskLevel").toString());
            if(riskLevel==0)other++;
            else if(riskLevel==1)low++;
            else if(riskLevel==2) middle++;
            else if(riskLevel==3) hight++;
        }
        StringBuffer sb = new StringBuffer();
        sb.append("监测周期内，共有").append(len).append("个监测指标，其中");
        sb.append(low).append("个指标监测结果良好，处于正常区域,");
        sb.append(middle).append("个指标处于预警区域,");
        sb.append(hight).append("个指标处于干预区域。");
        return sb.toString();
    }

    @Override
    public String getSuggestHightRisk(List<Map<String,Object>> datas) {
        StringBuffer sb = new StringBuffer();
        List<String> nameList = new ArrayList<>();
        for(int i=0;i<datas.size();i++) {
            Map<String, Object> data = datas.get(i);
            int cnt = Integer.parseInt(data.get("cnt").toString());
            int riskLevel = data.get("riskLevel")==null?0:Integer.parseInt(data.get("riskLevel").toString());
            if(riskLevel>1&&cnt>0){
                String name = data.get("name").toString();
                if(!nameList.contains(name)) {
                    nameList.add(name);
                }
            }
        }

        if(nameList.size()==0) {
            return null;
        }
        return String.join("，", nameList);
    }

    public String queryReportSubTitle(MetricStatReport metricStatReport) {
        List<Map<String, Object>> list = this.baseMapper.queryReportSubTitle(metricStatReport);
        StringBuffer sb = new StringBuffer();
        if (list.size() > 0) {
            Map<String, Object> retMap = list.get(0);
            Integer tp = metricStatReport.getTp();
            sb.append(retMap.get("curYear")).append("年");
            if (tp == 1) {
                //sb.append(retMap.get("curYear"));
            } else if (tp == 2) {
                sb.append(retMap.get("curWeek")).append("周");
            } else if (tp == 3) {
                sb.append(retMap.get("curMonth")).append("月");
            } else if (tp == 4) {
                sb.append(retMap.get("curQuarter")).append("季度");
            } else if (tp == 5) {
                sb.append("");
            } else if (tp == 6) {
                sb.append("");
            }
        }
        return sb.toString();
    }

    @Override
    public List<String> getSuggestContent(List<Map<String,Object>> datas) {

        List<String> retList = new ArrayList<>();
        for(int i=0;i<datas.size();i++) {
            Map<String, Object> data = datas.get(i);
            int riskLevel = data.get("riskLevel")==null?0:Integer.parseInt(data.get("riskLevel").toString());
            if(riskLevel<2) continue;
            if(data.get("tolVal")==null||data.get("warnVal")==null||data.get("fillVals")==null) continue;
            String strMtrcName = data.get("mtrcName").toString();
            float toVal = Float.valueOf(data.get("tolVal").toString());
            float warnVal = Float.valueOf(data.get("warnVal").toString());
            float fillVals = Float.valueOf(data.get("fillVals").toString());
            String strUnit = data.get("unit")==null?"":data.get("unit").toString();

            StringBuffer sb = new StringBuffer();

            if(toVal<warnVal) {
                if(riskLevel==3){
                    sb.append(strMtrcName).append("，高风险范围大于等于").append(warnVal).append(strUnit);
                    sb.append("，本期值为").append(fillVals).append(strUnit);
                } else if(riskLevel==2){
                    sb.append(strMtrcName).append("，中风险范围大于").append(toVal).append(strUnit)
                            .append("，小于").append(warnVal).append(strUnit);
                    sb.append("，本期值为").append(fillVals).append(strUnit);
                }
            } else {
                if(riskLevel==3){
                    sb.append(strMtrcName).append("，高风险范围小于等于").append(warnVal).append(strUnit);
                    sb.append("，本期值为").append(fillVals).append(strUnit);
                } else if(riskLevel==2){
                    sb.append(strMtrcName).append("，中风险范围小于").append(toVal).append(strUnit)
                    .append("，大于").append(warnVal).append(strUnit);
                    sb.append("，本期值为").append(fillVals).append(strUnit);
                }
            }
            if(sb.length()>0) {
                retList.add(sb.toString());
            }
        }

        return retList;
    }

    private Float calculate(Integer total, Integer val) {
        if (total == null || total == 0) return null;
        if (val == null) return null;

        DecimalFormat df = new DecimalFormat("#.##");
        df.setRoundingMode(RoundingMode.HALF_UP);  // 设置四舍五入

        double d = 100.00 * val / total;
        String result = df.format(d);
        return Float.parseFloat(result);
    }

}

