package cn.ibizlab.core.extensions.service;

import cn.ibizlab.core.analysis.domain.DABuild;
import cn.ibizlab.core.analysis.domain.DAChart;
import cn.ibizlab.core.analysis.domain.DAMetric;
import cn.ibizlab.core.analysis.domain.DAReport;
import cn.ibizlab.core.analysis.service.IDAChartService;
import cn.ibizlab.core.analysis.service.IDAMetricService;
import cn.ibizlab.core.analysis.service.impl.DAReportServiceImpl;
import cn.ibizlab.core.dict.extensions.service.DictDstService;
import cn.ibizlab.core.extensions.cql.ExecResultRepository;
import cn.ibizlab.core.extensions.dto.*;
import cn.ibizlab.core.extensions.util.ExcelTool;
import cn.ibizlab.core.rule.domain.ExecResult;
import cn.ibizlab.core.rule.service.IExecResultService;
import cn.ibizlab.util.dict.Catalog;
import cn.ibizlab.util.dict.CodeItem;
import cn.ibizlab.util.dict.CodeList;
import cn.ibizlab.util.dict.Option;
import cn.ibizlab.util.helper.DataObject;
import cn.ibizlab.util.helper.Setting;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.datastax.driver.core.PagingState;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.datastax.driver.core.querybuilder.QueryBuilder.lte;

@Service
@Primary
@Slf4j
public class BuildResultService {

    @Value("${cassandra.host:}")
    private String cassandraHost;

    @Autowired(required = false)
    @Lazy
    private ExecResultRepository execResultRepository;

    @Autowired
    @Lazy
    private DictDstService dictDstService;

    @Autowired
    @Lazy
    private DAReportServiceImpl daReportService;

    @Autowired
    @Lazy
    private IDAChartService daChartService;

    @Autowired
    @Lazy
    private IDAMetricService daMetricService;

    @Autowired
    @Lazy
    private DABuildExService daBuildExService;

    @Autowired
    @Lazy
    private DstDataSourceExService dstDataSourceService;

    @Autowired
    @Lazy
    private ExecResultExService execResultExService;

    @Autowired
    @Lazy
    BuildResultService proxy;

    @Value("${defaultResultDataSource:default}")
    private String Default_ResultDataSource;

    @Value("${defaultResultTableName:IBZRULERESULT}")
    private String Default_ResultTableName;


    public void prepareFetchParam(FetchParam fetchParam)
    {
        if(fetchParam.isFilled())
            return;
        Map<String, Set<String>> builds = null;
        if(ObjectUtils.isEmpty(fetchParam.getMetricIds()))
        {
            String vmConfig="";
            if(!StringUtils.isEmpty(fetchParam.getReportId()))
            {
                DAReport daReport = daReportService.getById(fetchParam.getReportId());
                if(daReport != null) {
                    vmConfig = daReport.getConfig();
                    if(!StringUtils.isEmpty(daReport.getDict()))
                        fetchParam.setDimDict(daReport.getDict());
                    else
                        fetchParam.setDimDict("CL_DST_REGION");

                    if(!StringUtils.isEmpty(daReport.getGroup()))
                        fetchParam.setGroup(daReport.getGroup());
                    fetchParam.setTitle(daReport.getReportName());
                }
            }
            else if(!StringUtils.isEmpty(fetchParam.getChartId()))
            {
                DAChart daChart = daChartService.getById(fetchParam.getChartId());
                if(daChart != null) {
                    vmConfig = daChart.getConfig();
                    if(!StringUtils.isEmpty(daChart.getDict()))
                        fetchParam.setDimDict(daChart.getDict());
                    else
                        fetchParam.setDimDict("CL_DST_REGION");

                    if(!StringUtils.isEmpty(daChart.getGroup()))
                        fetchParam.setGroup(daChart.getGroup());

                    fetchParam.setTitle(daChart.getChartName());
                }
            }


            if(!StringUtils.isEmpty(vmConfig)) {
                builds = VMConfig.getBuilds(vmConfig);
                List<String> ids= new ArrayList<>();
                builds.values().forEach(set->ids.addAll(set));
                fetchParam.setVmConfigs(JSONArray.parseArray(vmConfig,VMConfig.class));
                Map<String, DAMetric> metricMap = new LinkedHashMap<>();
                daMetricService.list(Wrappers.<DAMetric>lambdaQuery().in(DAMetric::getMetricId,ids)).forEach(item->{
                    metricMap.put(item.getMetricId(),item);
                    fetchParam.getMetricIds().add(item.getMetricId());
                });
                fetchParam.setMetrics(metricMap);
            }
            else
            {
                builds = new LinkedHashMap<>();
                if(!StringUtils.isEmpty(fetchParam.getBuildId())) {
                    Map<String, DAMetric> metricMap = new LinkedHashMap<>();
                    daMetricService.selectByBuildId(fetchParam.getBuildId()).forEach(item->{
                        metricMap.put(item.getMetricId(),item);
                        fetchParam.getMetricIds().add(item.getMetricId());
                    });
                    fetchParam.setMetrics(metricMap);
                    Set set=new LinkedHashSet();
                    set.addAll(fetchParam.getMetricIds());
                    builds.put(fetchParam.getBuildId(), set);
                }
            }


        }
        else// if(StringUtils.isEmpty(fetchParam.getReportId())&&StringUtils.isEmpty(fetchParam.getChartId())&&StringUtils.isEmpty(fetchParam.getBuildId()))
        {
            builds = new LinkedHashMap<>();
            Map<String, DAMetric> metricMap = new LinkedHashMap<>();
            List<DAMetric> list=daMetricService.list(Wrappers.<DAMetric>lambdaQuery().in(DAMetric::getMetricId,fetchParam.getMetricIds()));
            for(DAMetric item:list){
                metricMap.put(item.getMetricId(),item);
                if(!builds.containsKey(item.getBuildId()))
                    builds.put(item.getBuildId(),new LinkedHashSet());
                builds.get(item.getBuildId()).add(item.getMetricId());
            }
            fetchParam.setMetrics(metricMap);
        }

        if(!StringUtils.isEmpty(fetchParam.getDimDict())&&ObjectUtils.isEmpty(fetchParam.getDimItems())&&ObjectUtils.isEmpty(fetchParam.getDimValues()))
        {
            List<String> dimValues = new ArrayList<>();
            Catalog dict = dictDstService.getDictCatalog(fetchParam.getDimDict());

            if(StringUtils.isEmpty(fetchParam.getGroup()))
                fetchParam.setGroup(dict.getName());

            Assert.notNull(dict,"未找到数据字典"+fetchParam.getDimDict());
            Assert.notEmpty(dict.getOptions(),"未找到数据字典"+fetchParam.getDimDict());

            fetchParam.setDict(dict);

            Option dimItem = null;
            if(StringUtils.isEmpty(fetchParam.getDimValue())) {
                dimItem = dict.getOptions().get(0);
                fetchParam.setDimValue(dimItem.getValue().toString());
            }
            else
            {
                dimItem= dict.findCodeItem(fetchParam.getDimValue());
            }
            Assert.notNull(dimItem,"未找到数据字典项"+fetchParam.getDimDict()+"."+fetchParam.getDimValue());
            fetchParam.setDimItem(dimItem);
            if(fetchParam.isIncludeChild()&&dimItem.getChildren()!=null)
            {
                dimItem.getChildren().forEach(codeItem -> {
                    dimValues.add(codeItem.getValue().toString());
                });
            }
            if(dimValues.size()==0)
                dimValues.add(fetchParam.getDimValue());
            fetchParam.setDimValues(dimValues);
        }
        else if(!ObjectUtils.isEmpty(fetchParam.getDimItems())){
            String dimValue=fetchParam.getDimValue()==null?"%":fetchParam.getDimValue();
            Option dimItem = new Option().setValue(dimValue).setLabel("合计").setChildren(fetchParam.getDimItems());
            List<String> dimValues = new ArrayList<>();
            fetchParam.getDimItems().forEach(codeItem -> {
                dimValues.add(codeItem.getValue().toString());
            });
            fetchParam.setDimItem(dimItem);
            if(dimValues.size()==0)
                dimValues.add(fetchParam.getDimValue());
            fetchParam.setDimValues(dimValues);
        }
        else if(!ObjectUtils.isEmpty(fetchParam.getDimValues())){
            String dimValue=fetchParam.getDimValue()==null?"%":fetchParam.getDimValue();
            Option dimItem = new Option().setValue(dimValue).setLabel("合计");
            for(String dim:fetchParam.getDimValues()) {
                Option item = new Option().setValue(dim).setLabel(dim);
                if(dimItem.getChildren()==null)
                    dimItem.setChildren(new ArrayList<>());
                dimItem.getChildren().add(item);
            }
            fetchParam.setDimItem(dimItem);

        }

        if(builds!=null)
        {
            for(String key:builds.keySet())
            {
                DABuild daBuild = daBuildExService.getById(key);
                if(daBuild!=null)
                {
                    String resultDataSource = Setting.getValue(daBuild.getExtParams(), "resultDataSource");
                    String resultTableName = Setting.getValue(daBuild.getExtParams(), "resultTableName");
                    if(StringUtils.isEmpty(resultDataSource))
                        resultDataSource=Default_ResultDataSource;
                    if(StringUtils.isEmpty(resultTableName))
                        resultTableName=Default_ResultTableName;
                    String table=resultDataSource+"|"+resultTableName;
                    if(!fetchParam.getDimTables().containsKey(table))
                        fetchParam.getDimTables().put(table,builds.get(key));
                    else
                        fetchParam.getDimTables().get(table).addAll(builds.get(key));
                }

            }
        }

        fetchParam.setFilled(true);

    }


    public List<BuildResult> sum(FetchParam fetchParam)
    {
        return sum(fetchParam,null,null,null);
    }

    public List<BuildResult> sum(FetchParam fetchParam,Set<String> subMetricIds,Timestamp start,Timestamp end) {
        List<BuildResult> ret = new ArrayList<>();
        Timestamp startTime=(start==null)?fetchParam.getStartTime():start;
        Timestamp endTime=(end==null)?fetchParam.getEndTime():end;
        if(subMetricIds==null)
        {
            subMetricIds=new LinkedHashSet<>();
            for(DAMetric item:fetchParam.getMetrics().values()){
                if(!"AVG".equals(item.getMetricType()))
                    subMetricIds.add(item.getMetricId());
            }
        }

        if(!StringUtils.isEmpty(cassandraHost))
        {
            List<cn.ibizlab.core.extensions.cql.ExecResult> list=execResultRepository.sum(subMetricIds,1,fetchParam.getDimValues(),startTime,endTime);
            list.forEach(item->{
                ret.add(new BuildResult().setCqlResult(item));
            });
        }
        else
        {
            //prepareFetchParam(fetchParam);
            Map<String,Set<String>> tab = fetchParam.getDimTables();
            for(String key:tab.keySet()){
                String[] args = key.split("\\|");
                String dsName = args[0];
                String tableName = args[1];

                Set<String> tmpSet=new LinkedHashSet<>();
                for(String id:tab.get(key))
                {
                    if(subMetricIds.contains(id))
                        tmpSet.add(id);
                }
                if(tmpSet.size()>0)
                {
                    List<ExecResult> list = execResultExService.sumResult(dsName,tableName,new ArrayList<>(tmpSet),fetchParam.getDimValues(),startTime,endTime);
                    list.forEach(item->{
                        ret.add(new BuildResult().setSqlResult(item));
                    });
                }
            }



        }
        return ret;

    }

    public List<BuildResult> avg(FetchParam fetchParam)
    {
        return avg(fetchParam,null,null,null);
    }

    public List<BuildResult> avg(FetchParam fetchParam,Set<String> subMetricIds,Timestamp start,Timestamp end) {
        List<BuildResult> ret = new ArrayList<>();
        Timestamp startTime=(start==null)?fetchParam.getStartTime():start;
        Timestamp endTime=(end==null)?fetchParam.getEndTime():end;
        if(subMetricIds==null)
        {
            subMetricIds=new LinkedHashSet<>();
            for(DAMetric item:fetchParam.getMetrics().values()){
                if("AVG".equals(item.getMetricType()))
                    subMetricIds.add(item.getMetricId());
            }
        }

        if(!StringUtils.isEmpty(cassandraHost))
        {
            List<cn.ibizlab.core.extensions.cql.ExecResult> list=execResultRepository.avg(fetchParam.getMetricIds(),1,fetchParam.getDimValues(),startTime,endTime);
            list.forEach(item->{
                ret.add(new BuildResult().setCqlResult(item));
            });
        }
        else
        {
            //prepareFetchParam(fetchParam);
            Map<String,Set<String>> tab = fetchParam.getDimTables();
            for(String key:tab.keySet()){
                String[] args = key.split("\\|");
                String dsName = args[0];
                String tableName = args[1];


                Set<String> tmpSet=new LinkedHashSet<>();
                for(String id:tab.get(key))
                {
                    if(subMetricIds.contains(id))
                        tmpSet.add(id);
                }
                if(tmpSet.size()>0)
                {
                    List<ExecResult> list = execResultExService.avgResult(dsName,tableName,new ArrayList<>(tmpSet),fetchParam.getDimValues(),startTime,endTime);
                    list.forEach(item->{
                        ret.add(new BuildResult().setSqlResult(item));
                    });
                }

            }



        }
        return ret;

    }

    @Cacheable( value="dataAnalyse",key="'rows:lookup:'+#p0.getId()")
    public LookupResult lookup(FetchParam fetchParam) {
        prepareFetchParam(fetchParam);
        LookupResult lookupResult=new LookupResult();
        lookupResult.setDimValue(fetchParam.getDimValue());
        lookupResult.setMetricId(fetchParam.getMetricId());
        if(fetchParam.getMetrics()!=null)
            lookupResult.setMetric(fetchParam.getMetrics().get(fetchParam.getMetricId()));
        lookupResult.setPage(fetchParam.getPage()).setSize(fetchParam.getSize()).setTotal(fetchParam.getTotal()).setStartTime(fetchParam.getStartTime()).setEndTime(fetchParam.getEndTime());

        List<String> ret = new ArrayList<>();
        if(!StringUtils.isEmpty(cassandraHost))
        {
            PagingState pagingState = null;
            for (int i=0;i<=fetchParam.getPage();i++) {
                if (fetchParam.getPage() == i) {
                    ResultSet rs=execResultRepository.getPageData(fetchParam.getMetricId(),pagingState,fetchParam.getSize(), 1,fetchParam.getDimValue(),fetchParam.getStartTime(),fetchParam.getEndTime());
                    int remaining = rs.getAvailableWithoutFetching();
                    for (Row row : rs) {
                        ret.add(row.getString("keyvaluefield"));
                        if (--remaining == 0) {
                            break;
                        }
                    }
                    break;
                } else {
                    ResultSet rs=execResultRepository.getPageData(fetchParam.getMetricId(),pagingState,fetchParam.getSize(),1,fetchParam.getDimValue(),fetchParam.getStartTime(),fetchParam.getEndTime());
                    pagingState = rs.getExecutionInfo().getPagingState();
                }
            }

        }
        else
        {

            Map<String,Set<String>> tab = fetchParam.getDimTables();
            tab.keySet().forEach(key->{
                String[] args = key.split("\\|");
                String dsName = args[0];
                String tableName = args[1];

                Page<ExecResult> page = execResultExService.lookupResult(fetchParam.getPage(), fetchParam.getSize(), dsName, tableName, "keyvaluefield", fetchParam.getMetricId(), fetchParam.getDimValue(), fetchParam.getStartTime(), fetchParam.getEndTime());
                if(lookupResult.getTotal()==0||lookupResult.getTotal()==null)
                    lookupResult.setTotal((int)page.getTotalElements());
                page.getContent().forEach(item->{
                    ret.add(item.getKeyValueField());
                });
            });



        }
        lookupResult.setKeys(ret);
        lookupResult.setSnapTime(new Timestamp(System.currentTimeMillis()));
        return lookupResult;
    }


    @Cacheable( value="dataAnalyse",key="'rows:dr:'+#p0.getId()")
    public List<FetchItem> getResult(FetchParam fetchParam)
    {

        this.prepareFetchParam(fetchParam);

        Set<String> sum=new LinkedHashSet<>();
        Set<String> avg=new LinkedHashSet<String>();

        Set<String> sum_yoy=new LinkedHashSet<>();
        Set<String> sum_mom=new LinkedHashSet<>();
        Set<String> sum_y3=new LinkedHashSet<>();
        Set<DAMetric> sum_per=new LinkedHashSet<>();

        Set<String> avg_yoy=new LinkedHashSet<>();
        Set<String> avg_mom=new LinkedHashSet<>();
        Set<String> avg_y3=new LinkedHashSet<>();
        List<DAMetric> avg_per=new ArrayList<>();


        for(DAMetric metric:fetchParam.getMetrics().values())
        {
            if("AVG".equals(metric.getMetricType()))
            {
                avg.add(metric.getMetricId());
                if("YOY".equals(metric.getExtOp()))
                    avg_yoy.add(metric.getMetricId());
                else if("MOM".equals(metric.getExtOp()))
                    avg_mom.add(metric.getMetricId());
                else if("Y3".equals(metric.getExtOp()))
                    avg_y3.add(metric.getMetricId());
                else if("PER".equals(metric.getExtOp()) || "PER_ORI".equals(metric.getExtOp()))
                    avg_per.add(metric);

            }
            else
            {
                sum.add(metric.getMetricId());
                if("YOY".equals(metric.getExtOp()))
                    sum_yoy.add(metric.getMetricId());
                else if("MOM".equals(metric.getExtOp()))
                    sum_mom.add(metric.getMetricId());
                else if("Y3".equals(metric.getExtOp()))
                    sum_y3.add(metric.getMetricId());
                else if("PER".equals(metric.getExtOp()) || "PER_ORI".equals(metric.getExtOp()))
                    sum_per.add(metric);
            }
        }
        List<String> dims = new ArrayList<>();

        List<FetchItem> dimsObj = new ArrayList<>();
        Hashtable<String, FetchItem> dimsSet = new Hashtable<>();


        int no=1;
        if(fetchParam.isIncludeChild()&&fetchParam.getDimItem()!=null&&fetchParam.getDimItem().getChildren()!=null)
        {
            for(Option item:fetchParam.getDimItem().getChildren())
            {
                dims.add(item.getValue().toString());
                FetchItem obj=new FetchItem().setNo(no).setDimId(item.getValue().toString()).setDimName(item.getLabel()).setDisplayType(fetchParam.getDisplayType());

                for(DAMetric metric:fetchParam.getMetrics().values())
                {
                    obj.setVal(metric.getMetricId(),BigDecimal.ZERO);
                }
                dimsObj.add(obj);
                dimsSet.put(obj.getDimId(), obj);

                no++;
            }
        }
        boolean bcalsum=false;
        FetchItem sumobj=new FetchItem().setDisplayType(fetchParam.getDisplayType());
        {
            if(dims.size()==0)
                dims.add(fetchParam.getDimValue());
            else
                bcalsum=true;

            sumobj.setNo(no).setDimId(fetchParam.getDimValue()).setDimName((bcalsum||fetchParam.getDimItem()==null)?"合计":fetchParam.getDimItem().getLabel());
            for(DAMetric metric:fetchParam.getMetrics().values())
            {
                sumobj.setVal(metric.getMetricId(),BigDecimal.ZERO);
            }
            dimsObj.add(sumobj);
            dimsSet.put(sumobj.getDimId(), sumobj);
        }


        List<BuildResult> list=new ArrayList<>();

        if(sum.size()>0)
        {
            List<BuildResult> listsum = sum(fetchParam, sum, null, null);
            list.addAll(listsum);
        }
        if(avg.size()>0)
        {
            List<BuildResult> listavg = avg(fetchParam, avg, null, null);
            list.addAll(listavg);
        }

        for(BuildResult res:list)
        {
            if(!dimsSet.containsKey(res.getDimField()))
                continue;
            FetchItem obj=dimsSet.get(res.getDimField());
            obj.setVal(res.getRuleId(), res.getMetricField());
            if(bcalsum)
            {
                Double d=0d;
                if(res.getMetricField()!=null)
                {
                    d=res.getMetricField().doubleValue();
                }
                Double sumd=0d;
                if(sumobj.containsKey(res.getRuleId())&&sumobj.get(res.getRuleId())!=null)
                {
                    sumd=sumobj.getVal(res.getRuleId()).doubleValue();
                }
                sumd+=d;
                sumobj.setVal(res.getRuleId(), new BigDecimal(sumd).setScale(2, BigDecimal.ROUND_HALF_UP));
            }
        }


        //同比
        List<BuildResult> list_yoy=new ArrayList<>();
        if(sum_yoy.size()>0)
        {
            List<BuildResult> listsum=sum(fetchParam, sum_yoy, FetchParam.getLastYear(fetchParam.getStartTime()), FetchParam.getLastYear(fetchParam.getEndTime()));
            list_yoy.addAll(listsum);
        }
        if(avg_yoy.size()>0)
        {
            List<BuildResult> listavg=avg(fetchParam, avg_yoy, FetchParam.getLastYear(fetchParam.getStartTime()), FetchParam.getLastYear(fetchParam.getEndTime()));
            list_yoy.addAll(listavg);
        }

        for(BuildResult res:list_yoy)
        {
            if(!dimsSet.containsKey(res.getDimField()))
                continue;
            FetchItem obj=dimsSet.get(res.getDimField());
            Double now=obj.getVal(res.getRuleId()).doubleValue();
            Double last=res.getMetricField()==null?0d:res.getMetricField().doubleValue();
            if(last==0d)
            {
                last=1d;
                if(now==0d)
                    now=1d;
            }


            Double d=(now-last)/last;
            d=d*100;


            obj.setVal(res.getRuleId(), new BigDecimal(d).setScale(2, BigDecimal.ROUND_HALF_UP));
        }

        if(bcalsum)
        {

            HashMap<String,Double> sumlastset=new HashMap<String,Double>();
            for(BuildResult res:list_yoy)
            {
                Double sumlast=0d;
                Double d=0d;
                if(res.getMetricField()!=null)
                {
                    d=res.getMetricField().doubleValue();
                }

                if(sumlastset.containsKey(res.getRuleId())&&sumlastset.get(res.getRuleId())!=null)
                {
                    sumlast= sumlastset.get(res.getRuleId());
                }
                sumlast+=d;
                sumlastset.put(res.getRuleId(), sumlast);
            }
            for(String str:sumlastset.keySet())
            {

                Double now=sumobj.getVal(str).doubleValue();
                Double last=sumlastset.get(str);
                if(last==0d)
                {
                    last=1d;
                    if(now==0d)
                        now=1d;
                }


                Double d=(now-last)/last;
                d=d*100;

                sumobj.setVal(str, new BigDecimal(d).setScale(2, BigDecimal.ROUND_HALF_UP));
            }
        }

        //环比
        List<BuildResult> list_mom=new ArrayList<>();
        if(sum_mom.size()>0)
        {
            List<BuildResult> listsum=sum(fetchParam, sum_mom, FetchParam.getLastMonth(fetchParam.getStartTime()), FetchParam.getLastMonth(fetchParam.getEndTime()));
            list_mom.addAll(listsum);
        }
        if(avg_mom.size()>0)
        {
            List<BuildResult> listavg=avg(fetchParam, avg_mom, FetchParam.getLastMonth(fetchParam.getStartTime()), FetchParam.getLastMonth(fetchParam.getEndTime()));
            list_mom.addAll(listavg);
        }

        for(BuildResult res:list_mom)
        {
            if(!dimsSet.containsKey(res.getDimField()))
                continue;
            FetchItem obj=dimsSet.get(res.getDimField());
            Double now=obj.getVal(res.getRuleId()).doubleValue();
            Double last=res.getMetricField()==null?0d:res.getMetricField().doubleValue();
            if(last==0d)
            {
                last=1d;
                if(now==0d)
                    now=1d;
            }


            Double d=(now-last)/last;
            d=d*100;

            obj.setVal(res.getRuleId(), new BigDecimal(d).setScale(2, BigDecimal.ROUND_HALF_UP));
        }

        if(bcalsum)
        {

            HashMap<String,Double> sumlastset=new HashMap<String,Double>();
            for(BuildResult res:list_mom)
            {
                Double sumlast=0d;
                Double d=0d;
                if(res.getMetricField()!=null)
                {
                    d=res.getMetricField().doubleValue();
                }

                if(sumlastset.containsKey(res.getRuleId())&&sumlastset.get(res.getRuleId())!=null)
                {
                    sumlast= sumlastset.get(res.getRuleId());
                }
                sumlast+=d;
                sumlastset.put(res.getRuleId(), sumlast);
            }
            for(String str:sumlastset.keySet())
            {

                Double now=sumobj.getVal(str).doubleValue();
                Double last=sumlastset.get(str);
                if(last==0d)
                {
                    last=1d;
                    if(now==0d)
                        now=1d;
                }


                Double d=(now-last)/last;
                d=d*100;

                sumobj.put(str, new BigDecimal(d).setScale(2, BigDecimal.ROUND_HALF_UP));
            }
        }

        //占比
        sum_per.addAll(avg_per);

        for(DAMetric res:sum_per)
        {
            boolean isPerOri = false;
            if("PER_ORI".equalsIgnoreCase(res.getExtOp()))
                isPerOri = true;
            for(FetchItem obj:dimsObj)
            {
                if (StringUtils.isEmpty(obj.get(res.getMetricId())) || StringUtils.isEmpty(obj.get(res.getRefMetric()))) {
                    continue;
                }
                Double cur=obj.getVal(res.getMetricId()).doubleValue();
                Double per=obj.getVal(res.getRefMetric()).doubleValue();
                if(per==0d)
                    per=1d;
                Double d=(cur)/per;
                if(!isPerOri) {
                    d = d * 100;
                }
                obj.setVal(res.getMetricId(), new BigDecimal(d).setScale(2, BigDecimal.ROUND_HALF_UP));

            }



        }
        return dimsObj;
    }


    @Cacheable( value="dataAnalyse",key="'rows:cg:'+#p0.getId()")
    public FetchResult getReportConfig(FetchParam fetchParam)
    {
        String vmConfig="";
        if(!StringUtils.isEmpty(fetchParam.getReportId()))
        {
            DAReport daReport = daReportService.getById(fetchParam.getReportId());
            if(daReport != null) {
                vmConfig = daReport.getConfig();
                if(!StringUtils.isEmpty(daReport.getDict()))
                    fetchParam.setDimDict(daReport.getDict());
                else
                    fetchParam.setDimDict("CL_DST_REGION");

                if(!StringUtils.isEmpty(daReport.getGroup()))
                    fetchParam.setGroup(daReport.getGroup());
                fetchParam.setTitle(daReport.getReportName());
            }
        }
        else if(!StringUtils.isEmpty(fetchParam.getChartId()))
        {
            DAChart daChart = daChartService.getById(fetchParam.getChartId());
            if(daChart != null) {
                vmConfig = daChart.getConfig();
                if(!StringUtils.isEmpty(daChart.getDict()))
                    fetchParam.setDimDict(daChart.getDict());
                else
                    fetchParam.setDimDict("CL_DST_REGION");
                if(!StringUtils.isEmpty(daChart.getGroup()))
                    fetchParam.setGroup(daChart.getGroup());
                fetchParam.setTitle(daChart.getChartName());
            }
        }

        if(!StringUtils.isEmpty(vmConfig)) {
            fetchParam.setVmConfigs(JSONArray.parseArray(vmConfig,VMConfig.class));
        }

        if(!StringUtils.isEmpty(fetchParam.getDimDict())) {
            Catalog dict = dictDstService.getDictCatalog(fetchParam.getDimDict());
            if (StringUtils.isEmpty(fetchParam.getGroup()))
                fetchParam.setGroup(dict.getName());
            Assert.notNull(dict, "未找到数据字典" + fetchParam.getDimDict());
            Assert.notEmpty(dict.getOptions(), "未找到数据字典" + fetchParam.getDimDict());
            fetchParam.setDict(dict);
            Option dimItem = null;
            if (StringUtils.isEmpty(fetchParam.getDimValue())) {
                dimItem = dict.getOptions().get(0);
                fetchParam.setDimValue(dimItem.getValue().toString());
            }
        }

        return FetchResult.from(fetchParam);
    }

    @Cacheable( value="dataAnalyse",key="'rows:ar:'+#p0.getId()")
    public FetchResult getAnalyseResult(FetchParam fetchParam)
    {
        List<FetchItem> rows = this.getResult(fetchParam);
        return FetchResult.from(fetchParam).setRows(rows).setSnapId(fetchParam.getId()).setSnapTime(new Timestamp(System.currentTimeMillis()));
    }

    @CacheEvict( value = "dataAnalyse",allEntries = true)
    public void reset()
    {

    }



    public File exportExcel(FetchParam fetchParam) {
        FetchResult result=proxy.getAnalyseResult(fetchParam);
        Assert.notNull(result,"报表数据查询失败");
        Map<String, Object> resultDataMap = new HashMap<String, Object>();
        String headname = result.getTitle();// 报表名称
        Timestamp starttime = result.getStartTime();// 查询开始时间
        Timestamp endtime = result.getEndTime();// 查询结束时间
        List<Map<String,String>> titleList = new ArrayList<Map<String,String>>();
        {
            Map<String, String> titleMap = new HashMap<String, String>();
            titleMap.put("id", "report");
            titleMap.put("pid", "0");
            titleMap.put("content", headname);
            titleMap.put("fieldName", "report");
            titleList.add(titleMap);
        }

        {
            Map<String, String> titleMap = new HashMap<String, String>();
            titleMap.put("id", "filter");
            titleMap.put("pid", "report");
            titleMap.put("content", DataObject.dayFormat.format(result.getStartTime()).concat("到").concat(DataObject.dayFormat.format(result.getEndTime())));
            titleMap.put("fieldName", "filter");
            titleList.add(titleMap);
            this.onHandleColumn(result.getHeaders(),titleList,"filter");
        }



        return this.onCreateExcelFile(titleList, result.getRows(), headname, headname+fetchParam.getId(), starttime, endtime);
    }


    public List<Map<String,String>> onHandleColumn(List<VMConfig> headers,List<Map<String,String>> columnDataList,String pid) {
        if(columnDataList==null) columnDataList = new ArrayList<Map<String,String>>();
        if(StringUtils.isEmpty(pid)) pid="0";
        for(VMConfig col:headers){
            Map<String,String> titleMap = new HashMap<String,String>();
            String field = StringUtils.isEmpty(col.getField())? IdWorker.get32UUID():col.getField();
            if(col.isHide()) continue;
            titleMap.put("id", field);
            titleMap.put("pid", pid);
            titleMap.put("content",col.getHeaderName());
            titleMap.put("fieldName", field);
            columnDataList.add(titleMap);
            if(!ObjectUtils.isEmpty(col.getChildren()))
                onHandleColumn(col.getChildren(),columnDataList,field);
        }
        return columnDataList;
    }


    public File onCreateExcelFile(List<Map<String,String>> titleList, List<FetchItem> rowList, String headName, String fileName, Timestamp startTime, Timestamp endTime) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        String strNowDate = simpleDateFormat.format(date);
        String dirPath=System.getProperty("java.io.tmpdir") +"reportExcel" + File.separator + strNowDate + File.separator;
        File dir=new File(dirPath);
        if(!dir.exists())
            dir.mkdirs();
        String strFilePath = dirPath +fileName + ".xls";
        ExcelTool excelTool = new ExcelTool("报表", 20, 20);
        try {
            excelTool.exportExcel(excelTool.columnTransformer(titleList, "id", "pid", "content", "fieldName", "0"), rowList, strFilePath, true, false);
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        File file=new File(strFilePath);
        if(file.exists())
            return file;
        return null;
    }

}
