package cn.ibizlab.core.extensions.service;

import cn.ibizlab.core.analysis.domain.DADimension;
import cn.ibizlab.core.dict.extensions.service.DictDstService;
import cn.ibizlab.core.extensions.util.ExpiryMap;
import cn.ibizlab.core.rule.domain.ExecResult;
import cn.ibizlab.core.extensions.domain.BaseRequest;
import cn.ibizlab.core.lite.extensions.domain.FieldObj;
import cn.ibizlab.core.lite.extensions.domain.ModelObj;
import cn.ibizlab.core.rule.domain.ExecLog;
import cn.ibizlab.core.rule.service.IExecLogService;
import cn.ibizlab.core.rule.service.IExecResultService;
import cn.ibizlab.util.dict.CodeItem;
import cn.ibizlab.util.dict.CodeList;
import cn.ibizlab.util.helper.CachedBeanCopier;
import cn.ibizlab.util.helper.DataObject;
import lombok.extern.slf4j.Slf4j;
import org.kie.api.runtime.KieSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service("AnalyseEntityServiceImpl")
@ConditionalOnExpression("''.equals('${cassandra.host:}')")
public class AnalyseSqlServiceImpl extends BaseEntityServiceImpl {




    @Autowired
    @Lazy
    private DABuildExService daBuildExService;




    @Autowired
    private IExecResultService ruExecResultService;

    @Override
    public void saveResult(ModelObj param, String RULEID,String RULECODE, String RULENAME, String RU_EXECRESULTNAME, FieldObj BUSINESSCAT,
                           Integer RETVALUE, FieldObj KEYVALUEFIELD, FieldObj DOMAINSFIELD,FieldObj DIMFIELD,
                           FieldObj METRICFIELD, FieldObj TIMEFIELD, FieldObj EXT1FIELD, FieldObj EXT2FIELD)
    {
        ExecResult result=new ExecResult();
        result.setRuleId(RULEID);
        result.setRuleName(RULENAME);
        result.setName(RU_EXECRESULTNAME);
        result.setRetValue(RETVALUE);


        if(DOMAINSFIELD==null)
            DOMAINSFIELD=param.getEmpty();
        if(BUSINESSCAT==null)
            BUSINESSCAT=param.getEmpty();
        if(METRICFIELD==null)
            METRICFIELD=param.getEmpty();
        if(TIMEFIELD==null)
            TIMEFIELD=param.getEmpty();
        if(EXT1FIELD==null)
            EXT1FIELD=param.getEmpty();
        if(EXT2FIELD==null)
            EXT2FIELD=param.getEmpty();

        result.setKeyValueField(param.getRowKey());

        result.setBusinessCat(BUSINESSCAT.getValue(String.class,null));

        result.setMetricField(METRICFIELD.getDecimal());

        Timestamp timefield=TIMEFIELD.getValue(Timestamp.class,null);
        if(timefield!=null)
            result.setTimeField(timefield);



        String ext1=EXT1FIELD.getValues();
        if(ext1.length()>330)
            ext1=ext1.substring(0,330)+"...";
        if(!StringUtils.isEmpty(ext1))
            result.setExt1Field(ext1);


        String ext2=EXT2FIELD.getValues();
        if(ext2.length()>330)
            ext2=ext2.substring(0,330)+"...";
        if(!StringUtils.isEmpty(ext2))
            result.setExt2Field(ext2);

        result.setDomainsField(DOMAINSFIELD.getValue(String.class, ""));
        result.setSystemId(DataObject.getStringValue(param.get("systemid"),null));

        Object resultDataSource = Default_ResultDataSource;
        Object resultTableName = Default_ResultTableName;
        if(param.get("resultDataSource")!=null){
            resultDataSource = param.get("resultDataSource");
        }
        if(param.get("resultTableName")!=null){
            resultTableName = param.get("resultTableName");
        }
        result.set(Tag_EngineId,param.get(Tag_EngineId));
        result.set("resultDataSource", resultDataSource);
        result.set("resultTableName", resultTableName);

        if((!StringUtils.isEmpty(result.getRuleId()))&&(!StringUtils.isEmpty(result.getKeyValueField()))) {

            List<DADimension> dims=getDims(result.getBusinessCat());
            if(dims!=null) {

                for (DADimension dim : dims) {
                    String codevalue=param.$(dim.getField()).getValue(String.class,"");
                    if(!StringUtils.isEmpty(codevalue))
                    {
                        String dictname=dim.getDict();
                        Object val=codevalue;

                        if(!StringUtils.isEmpty(dictname))
                        {
                            CodeList codeList = this.getCodeListCatalog(dictname);
                            //维度指定代码表时，向上同时为每一个父节点添加一条数据
                            while(true)
                            {
                                CodeItem code= codeList.findCodeItem(val);
                                if(code!=null)
                                {
                                    ExecResult result2 = new ExecResult();
                                    CachedBeanCopier.copy(result, result2);
                                    result2.setDimField(code.getValue().toString());
                                    result2.setId(result2.getDefaultKey(true).toString());

                                    if(result2.getRetValue()==1)
                                        ruExecResultService.saveAsync(result2);
                                    else
                                        ruExecResultService.deleteAsync(result2);
                                    //非逐层核算或无父代码项退出
                                    if(dim.getRecursive() == 0 || StringUtils.isEmpty(code.getParent()))
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        val=code.getParent();
                                    }
                                }
                                else
                                    break;
                            }
                        }else{
                            //维度未指定代码表时，只保存一条数据
                            result.setDimField(codevalue);
                            result.setId(result.getDefaultKey(true).toString());
                            if(result.getRetValue()==1)
                                ruExecResultService.saveAsync(result);
                            else
                                ruExecResultService.deleteAsync(result);
                        }
                    }
                }
            }

        }

    }

    @Autowired
    protected IExecLogService ruExecLogService;
    public ExecLog processAll(BaseRequest msg)
    {

        ExecLog execlog=new ExecLog();
        execlog.setId(msg.getId());
        execlog.setRunBody(msg.toString());

        StringBuilder strErrorInfo=new StringBuilder();
        int count = 0;
        int errorcount = 0;

        String strResId=initRule(msg.getRules(),msg.getBatch());
        if (StringUtils.isEmpty(strResId))
        {
            strErrorInfo.append("准备rule文件错误");
            strErrorInfo.append("\r\n");
            execlog.setRetCode(2);
            execlog.setCnt(count);
            execlog.setSucc(errorcount);
            execlog.setRunResult(strErrorInfo.toString());
            ruExecLogService.update(execlog);
            return execlog;
        }

        try
        {


            for (ModelObj modelObj : msg.getDatas())
            {
                try
                {

                    count++;
                    modelObj.set("BATCH",msg.getBatch());
                    modelObj.set(Tag_EngineId, msg.getEngineId());
                    modelObj.set("systemid",msg.getSystemid());
                    if(!StringUtils.isEmpty(msg.getResultDataSource())){
                        modelObj.set("resultDataSource", msg.getResultDataSource());
                    }
                    if(!StringUtils.isEmpty(msg.getResultTableName())){
                        modelObj.set("resultTableName", msg.getResultTableName());
                    }
                    processRule(modelObj, modelObj.getRowKey(),strResId);

                }
                catch (Exception e)
                {
                    errorcount++;
                    log.error("Service错误，加载数据详细信息：" + modelObj.getRowKey() + "," + e.getMessage());
                    if (strErrorInfo.toString().length() <= 5000)
                    {
                        strErrorInfo.append("加载数据详细信息：" + modelObj.getRowKey() + ",错误：" + e.getMessage());
                        strErrorInfo.append("\r\n");
                        if (e.getCause() != null && e.getCause().getMessage() != null)
                        {
                            strErrorInfo.append(e.getCause().getMessage());
                            strErrorInfo.append("\r\n");
                        }

                    }

                }

            }






        }
        catch(Exception e)
        {
            log.error("Service读取BaseRequest错误:" + e.toString());
            strErrorInfo.append("读取BaseRequest错误:" + e.getMessage());
            strErrorInfo.append("\r\n");
            if (e.getCause() != null && e.getCause().getMessage() != null)
            {
                strErrorInfo.append(e.getCause().getMessage());
                strErrorInfo.append("\r\n");
            }


            execlog.setRetCode(1);
            execlog.setCnt(count);
            if (errorcount == 0)
                execlog.setSucc(0);
            else
                execlog.setSucc(count-errorcount);
            execlog.setRunResult(strErrorInfo.toString());
            ruExecLogService.update(execlog);
            return execlog;
        }
        finally
        {
            if(setkieSession.containsKey(strResId))
            {
                KieSession kieSession=setkieSession.get(strResId);
                try
                {
                    kieSession.dispose();
                }
                catch (Exception ex){}

                setkieSession.remove(strResId);
                setRuleCount.remove(strResId);
            }

        }

        log.info(new StringBuilder().append("Service成功，process successfully:").append(msg.toString()).toString());
        strErrorInfo.append("Service成功，process successfully\r\n");





        execlog.setCnt(count);
        execlog.setSucc(count-errorcount);
        if(execlog.getCnt()==0)
            execlog.setRetCode(3);
        else
            execlog.setRetCode(0);
        execlog.setRunResult(strErrorInfo.toString());
        this.ruExecLogService.update(execlog);
        return execlog;
    }


    private ExpiryMap<String,List<DADimension>> dimlistMap=new ExpiryMap<>();

    public List<DADimension>  getDims(String id)
    {
        List<DADimension> dims=dimlistMap.get("dims"+id);
        if(dims==null)
        {
            dims=daBuildExService.get(id).getDadimension();
            if(dims!=null)
                dimlistMap.put("dims"+id,dims);
        }
        return dims;
    }
}
