package com.nantian.cloud.jljc.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nantian.cloud.jljc.entity.*;
import com.nantian.cloud.jljc.mapper.EpcEnergyAccuracyAnalysisMapper;
import com.nantian.cloud.jljc.service.*;
import com.nantian.sc.cloud.common.core.util.R;
import com.nantian.sc.cloud.common.data.datascope.DataScope;
import com.nantian.sc.cloud.common.security.service.ScUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @date 2018-09-27
 */
@Service("epcEnergyAccuracyAnalysisService")
public class EpcEnergyAccuracyAnalysisServiceImpl extends ServiceImpl<EpcEnergyAccuracyAnalysisMapper, EpcEnergyAccuracyAnalysis> implements EpcEnergyAccuracyAnalysisService {

    @Autowired
    private EnterpriseInfoService enterpriseInfoService;
    @Autowired
    private EnergyLevelService energyLevelService;
    @Autowired
    private EnergyIndexService energyIndexService;
    @Autowired
    private TReportParaService tReportParaService;
    @Autowired
    private EpcEnergyAccuracyAnalysisInfoService epcEnergyAccuracyAnalysisInfoService;
    @Autowired
    private TReportUnitenergyService tReportUnitenergyService;

    final double NEGATIVE_INFINITY = -1.0 / 0.0;
    final double POSITIVE_INFINITY = 1.0 / 0.0;

    @Override
    public IPage<EpcEnergyAccuracyAnalysis> getPageScope(Page page, EpcEnergyAccuracyAnalysis epcEnergyAccuracyAnalysis) {
        return baseMapper.getPageScope(page, epcEnergyAccuracyAnalysis, new DataScope());
    }

    @Override
    public boolean getEpcEnergyAccuracyAnalysis(TReport report, double energyConsumption, DecimalFormat df, ScUser u) {
        EpcEnergyAccuracyAnalysis q = new EpcEnergyAccuracyAnalysis();
        q.setEpc(u.getEnterpriseCode());
        q.setYear(report.getYear() + "");
        q.setDelFlag("1");
        EpcEnergyAccuracyAnalysis old = baseMapper.selectOne(Wrappers.query(q));

        EpcEnergyAccuracyAnalysis analysis = new EpcEnergyAccuracyAnalysis();
        if (old != null) { //有历史数据为修改
            analysis.setId(old.getId());
        }

        String energyConsumptionStr = big(Float.parseFloat(df.format(energyConsumption)));
        analysis.setEpc(u.getEnterpriseCode());
        analysis.setYear(report.getYear() + "");
        analysis.setTotalEnergy(energyConsumptionStr);
        analysis.setUserid(u.getId());
        analysis.setDelFlag("1");
        //analysis.setDeptId(u.getDeptId());
        analysis.setUpdateTime(new Date());

        EnterpriseInfo info = enterpriseInfoService.getInfoNameByCode(u.getEnterpriseCode());
        if (info != null) {
            analysis.setDeptId(Integer.parseInt(info.getRegionCode()));
            analysis.setEpcName(info.getCmpName());
            analysis.setArea2(info.getRegionName());
            analysis.setTradeNum2(info.getIndustryName());
            analysis.setEpcType(info.getCompanyTypeName());
            analysis.setEnergyRegion(info.getEnergyConsumeLevelName());
            EnergyLevel level = energyLevelService.getById(info.getEnergyConsumeLevel());
            if (level != null) {
                analysis.setDifference((energyConsumption - Float.valueOf(level.getUpperLimit())) + ""); //变化值
                if (energyConsumption > Float.valueOf(level.getUpperLimit())) { //超出上限
                    analysis.setCheckResult("1"); //异常
                } else {
                    analysis.setCheckResult("2"); //正常
                }
            }
        }
        //return this.saveOrUpdate(analysis);
        int i = 0;
        if (analysis.getId() != null) {
            i = baseMapper.updateById(analysis);
        } else {
            i = baseMapper.insert(analysis);
        }
        return i == 0 ? false : true;
    }

    @Override
    public boolean getEpcEnergyAccuracyAnalysis3(TReport report, List<TReportUnitenergy> unitenergyList, ScUser u) {
        //获取企业信息
        EnterpriseInfo info = enterpriseInfoService.getInfoNameByCode(u.getEnterpriseCode());

        //取出平衡性预警区间
        TReportPara p = new TReportPara();
        p.setType("2");
        TReportPara para = tReportParaService.getOne(Wrappers.query(p));

        //获取精确性分析主表id
        Long id = getMainId(report, u);

        DecimalFormat df = new DecimalFormat(".00"); //保留两位小数
        for (TReportUnitenergy unitenergy : unitenergyList) {
            if (unitenergy.getGuidelineVal() != null && unitenergy.getGuidelineVal() != 0) {
                EpcEnergyAccuracyAnalysisInfo a = new EpcEnergyAccuracyAnalysisInfo();
                a.setDelFlag("1");
                a.setAbnormalVolatilityId(id);
                a.setDataTable("表3");
                a.setDataContent(unitenergy.getQuotaName());
                EpcEnergyAccuracyAnalysisInfo oldAnalysisInfo = epcEnergyAccuracyAnalysisInfoService.getOne(Wrappers.query(a));

                double change = 0;  //变化率
                double c = 0;       //差

                EnergyIndex i = new EnergyIndex();
                if(unitenergy.getQuotaId()!=null){
                    i.setId(unitenergy.getQuotaId());
                }else{
                    i.setIndexName(unitenergy.getQuotaName());
                    i.setDelFlag("1");
                }
                EnergyIndex energyIndex = energyIndexService.getOne(Wrappers.query(i));
                boolean flag = false; //无限额指标值

                if (energyIndex != null) { //有指标限额，与指标限额比对
                    if (energyIndex.getLocalLimit() != null && !"".equals(energyIndex.getLocalLimit()) && !"0".equals(energyIndex.getLocalLimit())) {
                        change = (unitenergy.getGuidelineVal() / Float.valueOf(energyIndex.getLocalLimit()) - 1) * 100;
                        c = unitenergy.getGuidelineVal() - Float.valueOf(energyIndex.getLocalLimit());
                        flag = true;
                    } else if (energyIndex.getGovLimit() != null && !"".equals(energyIndex.getGovLimit()) && !"0".equals(energyIndex.getGovLimit()) && energyIndex.getLocalLimit()!=null) {
                        change = (unitenergy.getGuidelineVal() / Float.valueOf(energyIndex.getGovLimit()) - 1) * 100;
                        c = unitenergy.getGuidelineVal() - Float.valueOf(energyIndex.getLocalLimit());
                        flag = true;
                    }
                }

                if (flag) { //有指标值
                    if (c != 0) { //指标值 超过或低于 指标限额
                        if (oldAnalysisInfo != null) {
                            oldAnalysisInfo.setUserid(u.getId());
                            oldAnalysisInfo.setUpdateTime(new Date());
                            oldAnalysisInfo.setLimits(energyIndex.getLocalLimit() != null ? energyIndex.getLocalLimit() : energyIndex.getGovLimit());
                            oldAnalysisInfo.setValue(unitenergy.getGuidelineVal().toString());
                            oldAnalysisInfo.setChangeRatio(Float.parseFloat(df.format(change)) + "%"); //变化率
                            oldAnalysisInfo.setDifference(Float.parseFloat(df.format(c)) + "");          //差值
                            epcEnergyAccuracyAnalysisInfoService.updateById(oldAnalysisInfo);
                        } else {
                            EpcEnergyAccuracyAnalysisInfo analysisInfo = new EpcEnergyAccuracyAnalysisInfo();
                            analysisInfo.setUserid(u.getId());
                            analysisInfo.setDelFlag("1");
                            analysisInfo.setDeptId(info != null ? Integer.parseInt(info.getRegionCode()) : u.getDeptId());
                            analysisInfo.setUpdateTime(new Date());
                            analysisInfo.setLimits(energyIndex.getLocalLimit() != null ? energyIndex.getLocalLimit() : energyIndex.getGovLimit());
                            analysisInfo.setValue(unitenergy.getGuidelineVal().toString());
                            analysisInfo.setChangeRatio(Float.parseFloat(df.format(change)) + "%");   //变化率
                            analysisInfo.setDifference(Float.parseFloat(df.format(c)) + "");            //差值
                            analysisInfo.setAbnormalVolatilityId(id);
                            analysisInfo.setDataTable("表3");
                            analysisInfo.setUnitVal(unitenergy.getQuotaUnit());
                            analysisInfo.setDataContent(unitenergy.getQuotaName());
                            epcEnergyAccuracyAnalysisInfoService.save(analysisInfo);
                        }
                    } else {
                        //沒有超出指标限额，却有记录，需删除
                        if (oldAnalysisInfo != null) {
                            deleteAnalysisInfo(u, oldAnalysisInfo);
                        }
                    }

                } else { //无指标限额，与该指标所有上年值的平均值做比较
                    //取出该指标所有上年值的平均值
                    String average = tReportUnitenergyService.getQuotaAverage(report.getYear() - 1, "3", unitenergy.getQuotaId());
                    if (average != null && !"".equals(average)) {
                        change = (unitenergy.getGuidelineVal() / Float.valueOf(average) - 1) * 100;
                        c = unitenergy.getGuidelineVal() - Float.valueOf(average);
                    }
                    if (change > Float.parseFloat(para.getUplimt())) {//指标值 超过 平衡性上限值
                        if (oldAnalysisInfo != null) {
                            oldAnalysisInfo.setUserid(u.getId());
                            oldAnalysisInfo.setUpdateTime(new Date());
                            oldAnalysisInfo.setValue(unitenergy.getGuidelineVal().toString());
                            oldAnalysisInfo.setAverage(Float.parseFloat(df.format(Float.valueOf(average))) + "");
                            oldAnalysisInfo.setDifference(Float.parseFloat(df.format(c)) + "");        //差值
                            oldAnalysisInfo.setChangeRatio(Float.parseFloat(df.format(change)) + "%"); //变化率
                            epcEnergyAccuracyAnalysisInfoService.updateById(oldAnalysisInfo);
                        } else {
                            EpcEnergyAccuracyAnalysisInfo analysisInfo = new EpcEnergyAccuracyAnalysisInfo();
                            analysisInfo.setUserid(u.getId());
                            analysisInfo.setDelFlag("1");
                            analysisInfo.setDeptId(info != null ? Integer.parseInt(info.getRegionCode()) : u.getDeptId());
                            analysisInfo.setUpdateTime(new Date());
                            analysisInfo.setAverage(Float.parseFloat(df.format(Float.valueOf(average))) + "");
                            analysisInfo.setFlag("T");  //平均值标志
                            analysisInfo.setValue(unitenergy.getGuidelineVal().toString());
                            analysisInfo.setDifference(Float.parseFloat(df.format(c)) + "");        //差值
                            analysisInfo.setChangeRatio(Float.parseFloat(df.format(change)) + "%"); //变化率
                            analysisInfo.setWarningRange(para.getDownlimt() + "% ～ " + para.getUplimt() + "%");
                            analysisInfo.setAbnormalVolatilityId(id);
                            analysisInfo.setDataTable("表3");
                            analysisInfo.setUnitVal(unitenergy.getQuotaUnit());
                            analysisInfo.setDataContent(unitenergy.getQuotaName());
                            epcEnergyAccuracyAnalysisInfoService.save(analysisInfo);
                        }
                    } else {
                        //沒有平衡性上限值，却有记录，需删除
                        if (oldAnalysisInfo != null) {
                            deleteAnalysisInfo(u, oldAnalysisInfo);
                        }
                    }
                }
            }

        }

        return true;
    }

    @Override
    public R getEpcEnergyAccuracyAnalysis4(TReport tReport, TReportRateprogress tReportRateprogress, ScUser u) {
        //取出平衡性预警区间
        TReportPara p = new TReportPara();
        p.setType("2");
        TReportPara para = tReportParaService.getOne(Wrappers.query(p));
        //给默认的平衡范围为 -20，20
        if (para.getUplimt() == null) {
            para.setUplimt("20");
        } else if (para.getDownlimt() == null) {
            para.setDownlimt("-20");
        }

        //获取精确性分析主表id
        Long id = getMainId(tReport, u);
        //保留两位小数
        DecimalFormat df = new DecimalFormat(".00");

        Map<String, Object> map1 = accuracyAnalysisTmp(
                u, para, id, df,
                "表4",
                tReportRateprogress.getTarget(),            //节能目标为标准
                tReportRateprogress.getEnergyProgress(),    //产值综合能耗实际完成进度节能量-当量值
                "产值综合能耗实际完成进度节能量（当量值）与进度节能量目标的变化比率，超出数据平衡性范围。若确定数值，请填写变化情况说明！",
                "产值综合能耗实际完成进度节能量（当量值）",
                "吨标准煤");
        if (map1 != null && map1.size() > 0) {
            return R.failed(map1);
        }

        Map<String, Object> map2 = accuracyAnalysisTmp(
                u, para, id, df,
                "表4",
                tReportRateprogress.getTarget(),                //节能目标为标准
                tReportRateprogress.getUnitEnergyProgress(),    //单位产品综合能耗实际完成进度节能量-当量值
                "单位产品综合能耗实际完成进度节能量（当量值）与进度节能量目标的变化比率，超出数据平衡性范围。若确定数值，请填写变化情况说明！",
                "单位产品综合能耗实际完成进度节能量（当量值）",
                "吨标准煤");
        if (map2 != null && map2.size() > 0) {
            return R.failed(map2);
        }


        /*Map<String, Object> map3 = accuracyAnalysisTmp(
                u, para, id, df,
                "表4",
                tReportRateprogress.getTarget(),                     //节能目标为标准
                tReportRateprogress.getEnergyProgressEqual(),      //产值综合能耗实际完成进度节能量-等价值
                "产值综合能耗实际完成进度节能量（等价值）与进度节能量目标的变化比率，超出数据平衡性范围。若确定数值，请填写变化情况说明！",
                "产值综合能耗实际完成进度节能量（等价值）",
                "吨标准煤");
        if (map3 != null && map3.size() > 0) {
            return R.failed(map3);
        }*/

        /*Map<String, Object> map4 = accuracyAnalysisTmp(
                u, para, id, df,
                "表4",
                tReportRateprogress.getTarget(),                     //节能目标为标准
                tReportRateprogress.getUnitEnergyProgressEqual(),    //单位产品综合能耗实际完成进度节能量-等价值
                "单位产品综合能耗实际完成进度节能量（等价值）与进度节能量目标的变化比率，超出数据平衡性范围。若确定数值，请填写变化情况说明！",
                "单位产品综合能耗实际完成进度节能量（等价值）",
                "吨标准煤");
        if (map4 != null && map4.size() > 0) {
            return R.failed(map4);
        }*/

        return null;
    }

    @Override
    public void removeInfoByReport( String tableName, TReport tReport) {
        List<EpcEnergyAccuracyAnalysis> analyses = baseMapper.selectList(new QueryWrapper<>(new EpcEnergyAccuracyAnalysis())
                .eq("del_flag", "1")
                .eq("epc", tReport.getEnterpriseCode())
                .eq("year", tReport.getYear()));
        if(analyses != null && analyses.size() > 0){ //主表有数据，查询其能报对应的子表信息
            List<EpcEnergyAccuracyAnalysisInfo> infos = epcEnergyAccuracyAnalysisInfoService.list(new QueryWrapper<>(new EpcEnergyAccuracyAnalysisInfo())
                    .eq("del_flag", "1")
                    .eq("abnormal_volatility_id", analyses.get(0).getId())
                    .in(StringUtils.isNotEmpty(tableName), "data_table", tableName.split(",")));
            if(infos != null && infos.size() > 0){ //删除精确分析
                for (EpcEnergyAccuracyAnalysisInfo info : infos) {
                    info.setDelFlag("4");
                }
                epcEnergyAccuracyAnalysisInfoService.updateBatchById(infos);
            }
        }
    }

    /**
     * 进行精确性分析
     *
     * @param u           用户
     * @param para        平衡范围
     * @param id          精确性信息主表id
     * @param df          保留精度
     * @param dataTable   数据表
     * @param limits      标准
     * @param value       数值
     * @param msg         提示内容
     * @param dataContent 数据内容
     * @param unit        单位
     */
    private Map<String, Object> accuracyAnalysisTmp(ScUser u, TReportPara para, Long id, DecimalFormat df,
                                                    String dataTable, Double limits, Double value, String msg, String dataContent, String unit) {

        //取出精确性分析详情表
        EpcEnergyAccuracyAnalysisInfo a = new EpcEnergyAccuracyAnalysisInfo();
        a.setDelFlag("1");
        a.setAbnormalVolatilityId(id);
        a.setDataTable(dataTable);
        a.setDataContent(dataContent);
        EpcEnergyAccuracyAnalysisInfo oldAnalysisInfo = epcEnergyAccuracyAnalysisInfoService.getOne(Wrappers.query(a));

        limits = (limits == null ? 0 : limits);
        value = (value == null ? 0 : value);
        double change = (value / limits - 1) * 100; //变化率
        double c = value - limits;                  //差值
        //if (limits != 0 && value != 0) {
        if (limits != 0 || value != 0) {
            //数值与标准的变化比率
            if (    Double.isInfinite(change) ||  //change为正无穷大 或负无穷大
                    change > Float.parseFloat(para.getUplimt()) || change < Float.parseFloat(para.getDownlimt())) { //超出平衡性范围
                if (oldAnalysisInfo == null) {
                    return getMap(para, id, df, dataTable, limits, value, msg, dataContent, unit, change, c);
                } else {
                    //更新精确性分析详情表的信息
                    oldAnalysisInfo.setUserid(u.getId());
                    oldAnalysisInfo.setUpdateTime(new Date());
                    oldAnalysisInfo.setLimits(limits.toString());
                    oldAnalysisInfo.setValue(value.toString());
                    oldAnalysisInfo.setDifference(Float.parseFloat(df.format(c)) + "");
                    //oldAnalysisInfo.setChangeRatio(Float.parseFloat(df.format(change)) + "%");
                    if (!(Double.isInfinite(change))) {
                        oldAnalysisInfo.setChangeRatio(Float.parseFloat(df.format(change)) + "%");
                    } else if (change == POSITIVE_INFINITY) {
                        oldAnalysisInfo.setChangeRatio("+∞");
                    } else {
                        oldAnalysisInfo.setChangeRatio("-∞");
                    }
                    oldAnalysisInfo.setWarningRange(para.getDownlimt() + "% ～ " + para.getUplimt() + "%");
                    epcEnergyAccuracyAnalysisInfoService.updateById(oldAnalysisInfo);
                }
            } else {
                //沒有平衡性上限值，却有记录，需删除
                if (oldAnalysisInfo != null) {
                    deleteAnalysisInfo(u, oldAnalysisInfo);
                }
            }
        }/* else {
            return getMap(para, id, df, dataTable, limits, value, msg, dataContent, unit, change, c);
        }*/

        return null;
    }

    /**
     * 超出平衡性范围，需填写说明的，需返回map
     */
    private Map<String, Object> getMap(TReportPara para, Long id, DecimalFormat df, String dataTable, Double limits, Double value, String msg, String dataContent, String unit, double change, double c) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("msg", msg);
        map.put("abnormalVolatilityId", id);
        map.put("dataTable", dataTable);
        map.put("dataContent", dataContent);
        map.put("unitVal", unit);
        map.put("limits", limits);
        map.put("value", value);
        //map.put("changeRatio", Float.parseFloat(df.format(change)) + "%"); //变化率
        if (!(Double.isInfinite(change))) {
            map.put("changeRatio", Float.parseFloat(df.format(change)) + "%");
        } else if (change == POSITIVE_INFINITY) {
            map.put("changeRatio", "+∞");
        } else {
            map.put("changeRatio", "-∞");
        }
        map.put("difference", Float.parseFloat(df.format(c)));             //差值
        map.put("warningRange", para.getDownlimt() + "% ～ " + para.getUplimt() + "%");
        return map;
    }


    /**
     * 沒有超出指标限额，却有记录，需删除
     */
    private void deleteAnalysisInfo(ScUser u, EpcEnergyAccuracyAnalysisInfo oldAnalysisInfo) {
        oldAnalysisInfo.setUserid(u.getId());
        oldAnalysisInfo.setUpdateTime(new Date());
        oldAnalysisInfo.setDelFlag("4");
        epcEnergyAccuracyAnalysisInfoService.updateById(oldAnalysisInfo);
    }

    /**
     * 获取主表id
     */
    private Long getMainId(TReport report, ScUser u) {
        //获取企业信息
        EnterpriseInfo info = enterpriseInfoService.getInfoNameByCode(u.getEnterpriseCode());

        Long id = 0L;
        EpcEnergyAccuracyAnalysis q = new EpcEnergyAccuracyAnalysis();
        q.setEpc(u.getEnterpriseCode());
        q.setYear(report.getYear() + "");
        q.setDelFlag("1");
        EpcEnergyAccuracyAnalysis old = baseMapper.selectOne(Wrappers.query(q));
        if (old == null) {
            EpcEnergyAccuracyAnalysis analysis = new EpcEnergyAccuracyAnalysis();
            analysis.setEpc(u.getEnterpriseCode());
            analysis.setYear(report.getYear() + "");
            analysis.setUserid(u.getId());
            analysis.setDelFlag("1");
            analysis.setDeptId(info != null ? Integer.parseInt(info.getRegionCode()) : u.getDeptId());
            analysis.setUpdateTime(new Date());
            int i = baseMapper.insert(analysis);
            if (i == 1) {
                id = analysis.getId();
            }
        } else {
            id = old.getId();
        }
        return id;
    }

    private static String big(double d) {
        NumberFormat nf = NumberFormat.getInstance();
        nf.setGroupingUsed(false);
        return nf.format(d);
    }

}

