package com.sys.bus.jx.service;

import com.jfinal.aop.Before;
import com.jfinal.aop.Enhancer;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.SqlPara;
import com.jfinal.plugin.activerecord.tx.Tx;
import com.sys.bus.hr.model.Person;
import com.sys.bus.model.*;
import com.sys.bus.syscode.service.SysCodeService;
import com.sys.core.utils.Conditions;
import com.sys.core.utils.Tool;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.script.*;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class KpilibService {
    BigDecimal largeData = new BigDecimal(999999999);
    BigDecimal smallData = new BigDecimal(-999999999);
    static OrgService orgService = Enhancer.enhance(OrgService.class);
    static SysCodeService codeService = Enhancer.enhance(SysCodeService.class);
    Log log = LogFactory.getLog(this.getClass());
    //
    /**
     * 保存Kpilib     算是否有自定义参数
     * @return id
     */
    @Before(Tx.class)
    public String saveKpilib(Kpilib kpilib,Person person){


        String id = kpilib.getKpilibId();
        String currTime = Tool.getCurrTime();
        String pid = person.getId();
        String pname = person.getName();
        String orgId = kpilib.getKpilibOrgid();
        String name = kpilib.getKpilibName();
        boolean add = false;
        if(StringUtils.isBlank(id)){
            kpilib.setKpilibId(Tool.uuid());
            kpilib.setKpilibCreatetime(currTime);
            kpilib.setKpilibCreatorname(pname);
            kpilib.setKpilibCreatorid(pid);
            add = true;
        }

        kpilib.setKpilibUpdatetime(currTime);
        kpilib.setKpilibUpdatename(pname);
        kpilib.setKpilibUpdateid(pid);
        kpilib.setKpilibStatus("1");
        if(orgId.equals("all")){
            kpilib.setKpilibOrgid(null);
        }
//        if(StringUtils.isNotBlank(kpilib.getKpilibOrgid()) && StringUtils.isNotBlank(kpilib.getKpilibOrgtype())){
//            throw new RuntimeException( "选择组织类型后，不能限定考核组织(可以选择公用)！限定考核组织时，请清空组织类型！！");
//        }

        Kpilib k = new Kpilib();
        k.setKpilibName(name);
        List<Kpilib> kpilibList = this.getKpilib(k);
        if(add){
//            if(kpilibList.size()>0){
//                String orgName = kpilibList.get(0).get("org_name");
//                throw new RuntimeException( "存在相同的指标名称！对应考核组织为："+(orgName==null?"公用":orgName));
//            }
            kpilib.save();
        }else{
//            for(Kpilib kpi:kpilibList){
//                if(!id.equals(kpi.getKpilibId())){
//                    String orgName = kpi.get("org_name");
//                    throw new RuntimeException( "存在相同的指标名称！对应考核组织为："+(orgName==null?"公用":orgName));
//                }
//            }
            kpilib.update();
        }
        return kpilib.getKpilibId();
    }
    private String getParamStr(Set<String> set){
        if(set == null||set.size()==0){
            return null;
        }
        String str = "";
        for(String s:set){
            str+=s+";";
        }
        return str.substring(0,str.length()-1);
    }
    private int findKey(String str,int expIndex){
        String key = "值";
        str = str.replace(">","-").replace("<","-").replace("=","-").replace("≥","-").replace("≤","-");
        //String key1 = "-值-";
        int index = str.indexOf("-值-");
        if(index<0){
            index = str.indexOf("值-");
        }else{
            return index+1;
        }
        if(index<0){
            index = str.indexOf("-值");
        }else{
            return index;
        }
        if(index<0){
            throw new RuntimeException("公式"+expIndex+ "未找到关键字：\"值\",或\"值\"前后无比较符！");
        }else{
            return index+1;
        }
    }
    private boolean isSign(String sign){
        //1≤ 2< 3>  4≥  5=
        if(sign.equals("≤") || sign.equals("<") ||sign.equals(">") ||sign.equals("≥") ||sign.equals("=")){
            return true;
        }
        return false;
    }

    /**
     * 根据map  把字符串中自定义参数替换成数字
     * @param str
     * @param map
     * @return
     */
    private String  setParamValue(String str,Map<String,BigDecimal> map){
        if(map ==null || map.size()==0)return str;
        for(String param:map.keySet()){
            str = str.replace("${"+param+"}",map.get(param).toString());
        }
        return str;
    }


    private String formatParamCode(String paramCode){
        return paramCode.replace("$", "").replace("{", "").replace("}", "");
    }


    /**
     * 解析自定义参数到Map
     * @param pvStr
     * @return
     */
     private Map<String,BigDecimal> parseParamValue(boolean test,String pvStr){
         Map<String,BigDecimal> map = new HashMap<String,BigDecimal>();
         if(StringUtils.isBlank(pvStr))return map;
         pvStr = pvStr.replace("，",",").replace("；",",").replace(";",",");
         pvStr = pvStr.replace("$","").replace("{","").replace("}","");
         String[] pv = pvStr.split(",");
         for (String s : pv) {
             if(StringUtils.isBlank(s))continue;
             String[] kv =  s.split(":");
             if(kv.length!=2||StringUtils.isBlank(kv[0])||StringUtils.isBlank(kv[1])){
                 throw new RuntimeException( "自定义参数"+(test?"测试":"")+"值设置错误");
             }
             try{
                 BigDecimal obj = new BigDecimal(kv[1]);
                 map.put(kv[0],obj);
             }catch (Exception e){
                 throw new RuntimeException( "自定义参数"+(test?"测试":"")+"值设置错误");
             }

         }

         return map;
     }


    private BigDecimal getExpFSData(String dataStr,Set<String> paramSet,Map<String,BigDecimal> paramValue,int expIndex){
        if(paramValue!=null){
            for(String param : paramSet){
                if(!paramValue.containsKey(param)){
                    throw new RuntimeException( "公式"+expIndex+ "需要为自定义参数<"+param+">赋值！");
                }
            }
            dataStr = this.setParamValue(dataStr,paramValue);
        }
        BigDecimal obj = this.eval(dataStr);
        if(obj==null)throw new RuntimeException( "公式"+expIndex+ "值设置有误，不能正常计算！");
        return obj;
    }

       /**
     * 启用禁用 Kpilib
     * @return
     */
    public int saveKpilib(boolean enable, String kpilibId, Person person){

        Kpilib kpilib = Kpilib.dao.findById(kpilibId);
        if(kpilib == null)return 3;
        kpilib.setKpilibStatus(enable?"1":"2");
        kpilib.setKpilibUpdateid(person.getId());
        kpilib.setKpilibUpdatename(person.getName());
        kpilib.setKpilibUpdatetime(Tool.getCurrTime());
        kpilib.update();
        return 0;
    }

    /**
     * 删除 Kpilib
     * @return 0 正常  1 被引用  2 没权限  3未找到
     */
    public int deleteKpilib(String kpilibId, Person person,boolean admin){

        Kpilib kpilib = Kpilib.dao.findById(kpilibId);
        if(kpilib == null)return 3;
        //
        if(!admin){
            String orgId = kpilib.getKpilibOrgid();
            List<Org> enableOrgList = orgService.getEnableOrgList(person.getId());
            if(!contains(enableOrgList,orgId)){
                return 2;
            }
        }
        Kpi kpi = new Kpi();
        kpi.setKpiBaseid(kpilibId);
        List<Kpi> list = Kpi.dao.find(this.getSqlPara(kpi));
        if(list.size()>0)return 1;
        kpilib.delete();
        log.info(person.getName()+"删除了kpi："+kpilib.getKpilibName());
        return 0;
    }

    private boolean contains( List<Org> list,String orgId){
        if(list.size()==0)return false;
        for(Org org : list){
            if(org.getOrgId().equals(orgId))return true;
        }
        return false;
    }

    /**
     * 获取所有所有KPIlib
     * @param personId
     * @return
     */
    public List<Kpilib> getKpilibList(String personId,boolean admin){

        List<String> orgTypeList = new ArrayList<>();
        SysCode sysCode = codeService.getSysCodeName("组织类型");
        String orgType = "集团,工控,地产";
        if(sysCode!=null && StringUtils.isNotBlank(sysCode.getSyscodeValue())){
            orgType = sysCode.getSyscodeValue().trim().replace("，",",");
        }

        for (String s : orgType.split(",")) {
            if(StringUtils.isBlank(s))continue;
            String code = s+"管理员";
            SysCode kpilibCode = codeService.getSysCodeName(code);
            if(kpilibCode!=null && personId.equals(kpilibCode.getSyscodeValue())){
                orgTypeList.add(s);
            }
        }

        String sql = "SELECT kpi.*,a.* FROM ct_jx_kpilib kpi  "
                +"  left join ct_jx_org a on a.org_id=kpi.kpilib_orgid  ";

        if(!admin && orgTypeList.size() ==0){
            sql+=" left join ct_jx_orgPerson op on op.orgperson_orgid = kpi.kpilib_orgid  WHERE  orgperson_pid =? or " +
                    " ((kpi.kpilib_orgid is null or kpi.kpilib_orgid ='') " +
                    "  and (kpi.kpilib_orgtype is null or kpi.kpilib_orgtype='' or kpi.kpilib_orgtype in (select org_type from ct_jx_orgPerson op left join ct_jx_org o on o.org_id=op.orgperson_orgid where orgperson_pid =?)) )";
        }else if(!admin && orgTypeList.size() >0){
            String orgTypeSql = "";
            for (String s : orgTypeList) {
                orgTypeSql +="'"+s+"',";
            }
            orgTypeSql= orgTypeSql.substring(0,orgTypeSql.length()-1);
            sql+=" left join ct_jx_orgPerson op on op.orgperson_orgid = kpi.kpilib_orgid  WHERE  orgperson_pid =? or " +
                    " ((kpi.kpilib_orgid is null or kpi.kpilib_orgid ='') " +
                       "  and (kpi.kpilib_orgtype is null or kpi.kpilib_orgtype='' or kpi.kpilib_orgtype in (select org_type from ct_jx_orgPerson op left join ct_jx_org o on o.org_id=op.orgperson_orgid where orgperson_pid =?)" +
                          " or  kpi.kpilib_orgtype in ("+orgTypeSql+")  ) )";

        }
        sql+=" order by kpilib_type,kpilib_status asc,kpilib_updatetime desc  ";
        List<Kpilib> list = null;
        if(admin){
            list =  Kpilib.dao.find(sql);
        }else{
            list =  Kpilib.dao.find(sql,personId,personId);
        }

        List<Org> orgList = orgService.getOrgList();
        Map<String,String> orgMap = new HashMap<>();
        for (Org org : orgList) {
            orgMap.put(org.getOrgId(),org.getOrgType());
        }
        for (Kpilib kpilib : list) {
            String kpilibOrgid = kpilib.getKpilibOrgid();
            String kpilibOrgType = kpilib.getKpilibOrgtype();
            if((StringUtils.isNotBlank(kpilibOrgid) && orgTypeList.contains(orgMap.get(kpilibOrgid))) ||
                    (StringUtils.isNotBlank(kpilibOrgType) && orgTypeList.contains(kpilibOrgType)) ){
                kpilib.put("kpiadmin",true);
            }
        }

        return list;
    }
    /**
     * 获取orgId能选取的所有不带自定义参数的 KPIlib
     * @param orgId
     * @return
     */
    public Page<Kpilib> getKpilibListNoField(String orgId,String kpiType,String kpiName,Integer  pageSize ,Integer pageNumber){
        String orgType = Org.dao.findById(orgId).getOrgType();

        String totalRowSql =
                "SELECT  count(*) FROM ct_jx_kpilib kpi  "
                        +" where ( kpilib_orgid =?  or kpilib_orgtype=? or((kpilib_orgtype=? or kpilib_orgtype is null or kpilib_orgtype ='') and  (kpilib_orgid is null or kpilib_orgid ='' ))) and kpilib_status =1  "
                        + (StringUtils.isNotBlank(kpiType)? " and  kpilib_type =? ":"")
                        + (StringUtils.isNotBlank(kpiName)? " and  kpilib_name like ? ":"");


        String findSql  = "SELECT kpi.* FROM ct_jx_kpilib kpi  "
                +" where ( kpilib_orgid =?  or kpilib_orgtype=? or((kpilib_orgtype=? or kpilib_orgtype is null or kpilib_orgtype ='') and   (kpilib_orgid is null or kpilib_orgid ='' ))) and kpilib_status =1  "
                + (StringUtils.isNotBlank(kpiType)? " and  kpilib_type =? ":"")
                + (StringUtils.isNotBlank(kpiName)? " and kpilib_name like ? ":"")
                +" order by kpilib_classify asc,kpilib_orgid asc,kpilib_updatetime desc  ";
        int len = 3;
        if(StringUtils.isNotBlank(kpiName))len++;
        if(StringUtils.isNotBlank(kpiType))len++;
        Object[] paras = new Object[len];

        paras[0] = orgId;
        paras[1] = orgType;
        paras[2] = orgType;
        if(StringUtils.isNotBlank(kpiType)) paras[3] = kpiType;
        if(StringUtils.isNotBlank(kpiName) && StringUtils.isBlank(kpiType)) paras[3] = "%"+kpiName+"%";
        if(StringUtils.isNotBlank(kpiName) && StringUtils.isNotBlank(kpiType)) paras[4] = "%"+kpiName+"%";

        Page<Kpilib> kpilibPage = Kpilib.dao.paginateByFullSql(pageNumber, pageSize, totalRowSql, findSql,paras);
        return kpilibPage;
    }
    /**
     * 获取orgId能选取的所有KPIlib
     * @param orgId
     * @return
     */
    public List<Kpilib> getKpilibList(String orgId){
        String orgType = Org.dao.findById(orgId).getOrgType();

        String sql = "SELECT kpi.* FROM ct_jx_kpilib kpi  "
                +" where ( kpilib_orgid =?  or kpilib_orgtype=? or((kpilib_orgtype=? or kpilib_orgtype is null or kpilib_orgtype ='' ) and  (kpilib_orgid is null or kpilib_orgid ='')))  and kpilib_status =1  "
                +" order by kpilib_orgid asc,kpilib_updatetime desc  ";
        List<Kpilib> list = null;

        list =  Kpilib.dao.find(sql,orgId,orgType,orgType);


        return list;
    }
    /**
     * 获取Kpilib List
     *
     * @param kpilib
     * @return
     */
    public List<Kpilib> getKpilib(Kpilib kpilib) {
        List<Kpilib> list = Kpilib.dao.find(this.getSqlPara(kpilib));

        return list;
    }

    /**
     * 获取Kpilib的 SqlPara
     *
     * @param kpilib
     * @return
     */
    private SqlPara getSqlPara(Kpilib kpilib) {
        Conditions condi = new Conditions();
        condi.modelToCondition(kpilib);
        SqlPara sp = condi.getSqlPara();
        String sql = sp.getSql();
        int where = sql.indexOf(" where ");
        if(where>-1){
            sql = sql.substring(0,where)+ " left join ct_jx_org org on org.org_id =kpilib_orgid   left join t_org_admin a on a.fid=kpilib_orgid "+sql.substring(where);
        }else{
            sql += " left join ct_jx_org org on org.org_id =kpilib_orgid  left join t_org_admin a on a.fid=kpilib_orgid ";
        }
        sql+=" order by kpilib_orgid,kpilib_status asc,kpilib_createtime desc ";
        sp.setSql(sql);
        return sp;
    }
    private SqlPara getSqlPara(Kpi kpi) {
        Conditions condi = new Conditions();
        condi.modelToCondition(kpi);
        SqlPara sp = condi.getSqlPara();
        return sp;
    }
    private BigDecimal eval( String script){
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");
        Compilable compilable = (Compilable) engine;
        Bindings bindings = engine.createBindings(); //Local级别的Binding
       // String script = "(1+0.1 * (F/100) * T)*P0"; //定义函数并调用
        CompiledScript JSFunction = null; //解析编译脚本函数
        try {
            JSFunction = compilable.compile(script);
//            bindings.put("F", 2.5);
//            bindings.put("T", 30);
//            bindings.put("A", 100);
//            bindings.put("P0", 100);
            Object obj =  JSFunction.eval(bindings);
            if(obj instanceof  Double){
                return new BigDecimal((Double)obj);
            }else if(obj instanceof  Integer){
                return new BigDecimal((Integer)obj);
            }else if(obj instanceof  Float){
                return new BigDecimal((Float)obj);
            }else if(obj instanceof  Long){
                return new BigDecimal((Long)obj);
            }
            throw  new ScriptException("公式数字类型异常："+obj.getClass());
        } catch (ScriptException e) {
            log.error("公式计算失败",e);
            return null;
        }
    }


    private static boolean isContainChinese(String str) {
        Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
        Matcher m = p.matcher(str);
        if (m.find()) {
            return true;
        }
        return false;
    }

}
