package cn.com.ctop.alarm.modules.constant;

import cn.com.ctop.alarm.modules.entity.RuleGroup;
import cn.com.ctop.common.module.utils.Check;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xxl.job.core.enums.NoEn;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * @ClassName MatchLogic
 * @Author ZHAOXA
 * @date 2020-11-17 10:54
 */
@Slf4j
public class MatchLogic {
    /**
     * @param indicator      数据类型
     * @param condition 条件
     * @param threshold 阈值
     * @param value     比对值
     * @return boolean
     * @throws
     * @author ZHAOXA
     */
    public static boolean matchCondition(JSONObject indicator, String condition, String threshold, String value, JSONObject obj, String indicatorCode) {
        //阈值数据类型类型
        String type = indicator.getString("dataType");
        try {
            if (Check.isNull(threshold) || "[]".equals(threshold)) {
                return false;
            }
            if (Check.isNull(value) || "[]".equals(value)) {
                //洗出的数据为空的时候不报警，若想报警则改成true
                obj.put("isNull", false);
                return false;
            }
            obj.put("isNull", false);
            if ("number".equals(type)) {
                BigDecimal bigVal = new BigDecimal(value);
                if (threshold.contains("~")) {
                    String[] split = threshold.split("~");
                    BigDecimal min = new BigDecimal(split[0]);
                    BigDecimal max = new BigDecimal(split[1]);
                    //bigVal介于min与max之间，即：min<=bigVal<=max
                    if (max.compareTo(bigVal) > -1 && bigVal.compareTo(min) > -1) {
                        return true;
                    } else {
                        return false;
                    }
                }
                BigDecimal bigThr = new BigDecimal(threshold);
                switch (condition) {
                    case "equal":
                        return bigVal.compareTo(bigThr) == 0;
                    case "not_equal":
                        return bigVal.compareTo(bigThr) != 0;
                    case "greater":
                        return bigVal.compareTo(bigThr) > 0;
                    case "less":
                        return bigVal.compareTo(bigThr) < 0;
                    case "greater_equal":
                        return bigVal.compareTo(bigThr) >= 0;
                    case "less_equal":
                        return bigVal.compareTo(bigThr) <= 0;
                    default:
                        log.warn("关系不匹配 type={},condition={},threshold={},value={},", type, condition, threshold, value);
                        break;
                }
            } else if ("string".equals(type)) {
                if (threshold.contains("[")) {
                    List<String> thresholds = strToList(threshold);
                    if ("equal".equals(condition)) {
                        return value.equals(thresholds.get(0));
                    } else if ("not_equal".equals(condition)) {
                        return !value.equals(thresholds.get(0));
                    } else if ("contain".equals(condition)) {
                        if (thresholds.toString().contains(value)) {
                            return true;
                        }
                    } else if ("no_contain".equals(condition)) {
                        if (!thresholds.toString().contains(value)) {
                            return true;
                        }
                    }
                } else {
                    switch (condition) {
                        case "equal":
                            return value.equals(threshold);
                        case "not_equal":
                            return !value.equals(threshold);
                        case "contain":
                            return value.contains(threshold);
                        case "no_contain":
                            return !value.contains(threshold);
                        default:
                            log.warn("关系不匹配 type={},condition={},threshold={},value={},", type, condition, threshold, value);
                            return false;
                    }
                }
            } else {
                /**
                 不包含逻辑根据指标分两种：
                 1、大部分数组型指标阈值逻辑：所设的阈值中，存在任一目标则不报警，都不存在时则报警,出现阈值之外的亦报警
                 2、排除人群包、排除流量包逻辑：所选必须都存在，否则报警

                 包含逻辑通用： 任一存在则报警
                 */
                if (value.contains("[") && threshold.contains("[")) {
                    String logicalType = indicator.getString("logicalType");
                    List<String> values = strToList(value);
                    List<String> thresholds = strToList(threshold);
                    //包含 任一存在则报警
                    if ("contain".equals(condition)) {
                        //人群包、流量包判断的是对象
                        if (NoEn.NO1.valueStr().equals(logicalType) || "retargetingTagsInclude".equals(indicatorCode) || "population".equals(indicatorCode) || "district".equals(indicatorCode) || "region".equals(indicatorCode)) {
                            for (String thr : thresholds) {
                                if (values.contains(thr)) {
                                    return true;
                                }
                            }
                        } else {
                            for (String thr : thresholds) {
                                if (values.toString().contains(thr)) {
                                    return true;
                                }
                            }
                        }
                    } else {
                        //排除人群包、流量排除包逻辑,不包含，所选必须都存在，否则报警
                        if (NoEn.NO1.valueStr().equals(logicalType)) {
                            if (values.size() != thresholds.size()) {
                                return true;
                            }
                            values.sort(Comparator.comparing(String::hashCode));
                            thresholds.sort(Comparator.comparing(String::hashCode));
                            return !values.toString().equals(thresholds.toString());

                        } else {
                            //不包含，阈值中，存在任一目标则不报警，都不存在时则报警,出现阈值之外的亦报警
                            boolean flag = true;
                            //人群包判断是否存在该对象
                            for (String v : values) {
                                if (threshold.contains(v)) {
                                    flag = false;
                                } else {
                                    return true;
                                }
                            }
                            return flag;
                        }
                    }
                } else if (threshold.contains("[")) {
                    List<String> thresholds = strToList(threshold);
                    if ("contain".equals(condition)) {
                        for (String thr : thresholds) {
                            if (value.toString().contains(thr)) {
                                return true;
                            }
                        }
                    } else {
                        for (String thr : thresholds) {
                            if (!value.contains(thr)) {
                                return true;
                            }
                        }
                    }
                } else {
                    if ("contain".equals(condition)) {
                        return value.contains(threshold);
                    } else {
                        return !value.contains(threshold);
                    }
                }
            }
        } catch (
                Exception e) {
            log.error("条件匹配异常,入参为：type={},condition={},threshold={},value={},", type, condition, threshold, value, e);
        }
        return false;
    }

    /**
     * 整理发送的消息
     */
    public static String getMsg(RuleGroup ruleGroup, JSONObject user, JSONObject obj, boolean isPause, String accountName) {
        Long creativeId = obj.getLong("creativeId");
        Long planId = obj.getLong("planId");
        Long accountId = obj.getLong("accountId");
        boolean isNull = obj.getBoolean("isNull");
        StringBuffer header = new StringBuffer();
        header.append(ruleGroup.getGroupName()).append("预警").append("<br/>").
                append("预警账户：").append(accountId).append("，授权名称为：").append(accountName).append("<br/>");
        if (!Check.isNull(planId) && !Check.isNull(creativeId)) {
            header.append("预警计划：").append(planId).append("<br/>").append("预警创意：").append(creativeId).append("<br/>");
        } else if (!Check.isNull(planId) && Check.isNull(creativeId)) {
            header.append("预警计划：").append(planId).append("<br/>");
        } else if (!Check.isNull(creativeId)) {
            header.append("预警创意：").append(creativeId).append("<br/>");
        }
        if (isNull) {
            header.append("该规则未匹配到投放数据").append("<br/>");
        }
        if (isPause) {
            header.append("现已被关停，请您及时查看并调整！");
        } else {
            header.append("请您及时查看并调整！");
        }
        return header.toString();
    }

    /**
     * 整理发送的消息
     */
    public static String getMessage(String ruleGroupName, Long accountId, String accountName, String type, String codes, boolean isNull) {
        StringBuffer buf = new StringBuffer();
        buf.append(ruleGroupName).append("预警").append("<br/>").
                append("预警账户：").append(accountId).append("，授权名称：").append(accountName).append("<br/>");
        if ("plan".equals(type)) {
            buf.append("预警计划：").append(codes).append("<br/>");
        } else if ("unit".equals(type)) {
            buf.append("预警组：").append(codes).append("<br/>");
        } else if ("creative".equals(type)) {
            buf.append("预警创意：").append(codes).append("<br/>");
        }
        if (isNull) {
            buf.append("该规则未匹配到投放数据").append("<br/>");
        }
        return buf.toString();
    }

    //拆分逗号拼接数据
    public static List<String> strToList(String strings) {
        List<String> ids = null;
        try {
            if (Check.isNull(strings)) {
                return null;
            }
            JSONObject job = new JSONObject();
            job.put("list", strings);
            ids = new ArrayList<>();
            JSONArray idList = job.getJSONArray("list");
            for (Object id : idList) {
                ids.add(String.valueOf(id));
            }
        } catch (Exception e) {
            log.error("数据（{}）转list异常", strings, e);
        }
        return ids;
    }

    public static JSONArray getSendData(JSONArray accountDatas, JSONArray planDatas, JSONArray creativeDatas, JSONArray targetDatas) {
        JSONArray sendData = new JSONArray();
        if (!Check.isNull(accountDatas) && Check.isNull(planDatas) && Check.isNull(creativeDatas) && Check.isNull(targetDatas)) {
            sendData = accountDatas;
        } else {
            if (!Check.isNull(planDatas) && Check.isNull(creativeDatas) && Check.isNull(targetDatas)) {
                sendData = planDatas;
            } else if (!Check.isNull(creativeDatas) && Check.isNull(planDatas) && Check.isNull(targetDatas)) {
                sendData = creativeDatas;
            } else if (!Check.isNull(targetDatas) && Check.isNull(planDatas) && Check.isNull(creativeDatas)) {
                sendData = targetDatas;
            } else if (!Check.isNull(planDatas) && !Check.isNull(creativeDatas) && !Check.isNull(targetDatas)) {
                for (int i = 0; i < planDatas.size(); i++) {
                    Long pplanId = planDatas.getJSONObject(i).getLong("planId");
                    for (int k = 0; k < targetDatas.size(); k++) {
                        Long tplanId = targetDatas.getJSONObject(k).getLong("planId");
                        for (int j = 0; j < creativeDatas.size(); j++) {
                            Long cplanId = creativeDatas.getJSONObject(j).getLong("planId");
                            if (cplanId.equals(tplanId) && cplanId.equals(pplanId)) {
                                sendData.add(creativeDatas.getJSONObject(j));
                            }
                        }
                    }
                }
            } else if (!Check.isNull(planDatas) && !Check.isNull(targetDatas) && Check.isNull(creativeDatas)) {
                for (int i = 0; i < planDatas.size(); i++) {
                    Long pplanId = planDatas.getJSONObject(i).getLong("planId");
                    for (int k = 0; k < targetDatas.size(); k++) {
                        Long tplanId = targetDatas.getJSONObject(k).getLong("planId");
                        if (tplanId.equals(pplanId)) {
                            sendData.add(targetDatas.getJSONObject(k));
                        }
                    }
                }
            } else if (!Check.isNull(planDatas) && Check.isNull(targetDatas) && !Check.isNull(creativeDatas)) {
                for (int i = 0; i < planDatas.size(); i++) {
                    Long pplanId = planDatas.getJSONObject(i).getLong("planId");
                    for (int k = 0; k < creativeDatas.size(); k++) {
                        Long cplanId = creativeDatas.getJSONObject(k).getLong("planId");
                        if (cplanId.equals(pplanId)) {
                            sendData.add(creativeDatas.getJSONObject(k));
                        }
                    }
                }
            } else if (Check.isNull(planDatas) && !Check.isNull(targetDatas) && !Check.isNull(creativeDatas)) {
                for (int i = 0; i < targetDatas.size(); i++) {
                    Long tplanId = targetDatas.getJSONObject(i).getLong("planId");
                    for (int k = 0; k < creativeDatas.size(); k++) {
                        Long cplanId = creativeDatas.getJSONObject(k).getLong("planId");
                        if (cplanId.equals(tplanId)) {
                            sendData.add(creativeDatas.getJSONObject(k));
                        }
                    }
                }
            }
        }
        return sendData;
    }

    /**
     * 快手匹配达标数据
     *
     * @param
     * @return com.alibaba.fastjson.JSONArray
     * @throws
     * @author ZHAOXA
     */
    public static JSONArray getKuaiShouSendData(JSONArray accountDatas, JSONArray planDatas, JSONArray groupDatas, JSONArray creativeDatas, JSONArray targetDatas) {
        JSONArray sendData = new JSONArray();
        if (!Check.isNull(accountDatas) && Check.isNull(groupDatas) && Check.isNull(planDatas) && Check.isNull(creativeDatas) && Check.isNull(targetDatas)) {
            sendData = accountDatas;
        } else {
            if (Check.isNull(planDatas)) {
                if (!Check.isNull(groupDatas) && Check.isNull(creativeDatas) && Check.isNull(targetDatas)) {
                    sendData = groupDatas;
                } else if (Check.isNull(groupDatas) && !Check.isNull(creativeDatas) && Check.isNull(targetDatas)) {
                    sendData = creativeDatas;
                } else if (Check.isNull(groupDatas) && Check.isNull(creativeDatas) && !Check.isNull(targetDatas)) {
                    sendData = targetDatas;
                }
            } else {
                if (Check.isNull(groupDatas) && Check.isNull(creativeDatas) && Check.isNull(targetDatas)) {
                    sendData = planDatas;
                } else {
                    for (int i = 0; i < planDatas.size(); i++) {
                        Long planId = planDatas.getJSONObject(i).getLong("planId");
                        if (!Check.isNull(targetDatas) && Check.isNull(groupDatas)) {
                            for (int k = 0; k < targetDatas.size(); k++) {
                                Long tgPlanId = targetDatas.getJSONObject(k).getLong("planId");
                                if (tgPlanId.equals(planId)) {
                                    sendData.add(creativeDatas.getJSONObject(k));
                                }
                            }
                        } else if (Check.isNull(targetDatas) && !Check.isNull(groupDatas)) {
                            for (int k = 0; k < groupDatas.size(); k++) {
                                Long tgPlanId = groupDatas.getJSONObject(k).getLong("planId");
                                if (tgPlanId.equals(planId)) {
                                    sendData.add(creativeDatas.getJSONObject(k));
                                }
                            }
                        }
                    }
                }
            }
        }
        return sendData;
    }

}
