package com.tzld.piaoquan.recommend.server.util;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class FeatureUtils {
    public static final String cate1Attr = "cate1_list";
    public static final String cate2Attr = "cate2";
    public static final String festive1Attr = "festive_label1";
    public static final String channelAttr = "channel";
    public static final String sourceAttr = "vid_source";
    public static final String uidAttr = "uid";
    public static final String mergeCate1Attr = "merge_first_level_cate";
    public static final String mergeCate2Attr = "merge_second_level_cate";
    public static final double twoMonthMs = 2 * 30 * 24 * 3600 * 1000.0;

    private static final String goodMorningRegex = "(早安|早上好|早晨好|上午好)";
    private static final String goodAfternoonRegex = "(午安|中午好|下午好)";
    private static final String goodEveningRegex = "(晚安|晚上好)";
    private static final Pattern goodMorningPattern = Pattern.compile(goodMorningRegex);
    private static final Pattern goodAfternoonPattern = Pattern.compile(goodAfternoonRegex);
    private static final Pattern goodEveningPattern = Pattern.compile(goodEveningRegex);
    private static final Map<String, String[]> userChannelPrefixMap = new HashMap<>();

    static {
        // 公众号买号 & 公众号代运营-Daily, 需要二次判断
        userChannelPrefixMap.put("公众号mix", new String[]{"longArticles_"});
        userChannelPrefixMap.put("公众号代运营-即转", new String[]{"dyyjs_"});
        userChannelPrefixMap.put("小程序投流", new String[]{"touliu_tencent_"});
        userChannelPrefixMap.put("公众号投流", new String[]{"touliu_tencentgzh_", "touliu_tencentGzhArticle_", "GzhTouLiu_Articles_gh"});
        userChannelPrefixMap.put("测-企微投放", new String[]{"touliu_tencentqw_", "WeCom_"});
        userChannelPrefixMap.put("测-企微合作", new String[]{"touliu_tencentwbqw_", "dyyqw_"});
        userChannelPrefixMap.put("停-公众号合作", new String[]{"gzhhz_"});
        userChannelPrefixMap.put("测-公众号完全代投放", new String[]{"daitou_tencentgzh", "DaiTou_gh"});
    }

    public static int judgeVideoTimeType(String s) {
        if (null != s && !s.isEmpty()) {
            Matcher morning = goodMorningPattern.matcher(s);
            if (morning.find()) {
                return 1;
            }
//            Matcher afternoon = goodAfternoonPattern.matcher(s);
//            if (afternoon.find()) {
//                return 2;
//            }
//            Matcher evening = goodEveningPattern.matcher(s);
//            if (evening.find()) {
//                return 3;
//            }
        }
        return 0;
    }

    public static double getTimeDiff(long currentMs, long historyMs) {
        double diff = (currentMs - historyMs) / twoMonthMs;
        if (diff > 1.0) {
            diff = 1.0;
        }
        return diff;
    }

    public static double log1(double data) {
        if (data <= 0) {
            return 0D;
        }
        return Math.log(data + 1.0);
    }

    public static double log1(double data, double scale) {
        if (data <= 0) {
            return 0D;
        }
        return Math.log(data + 1.0) / scale;
    }

    public static double plusSmooth(double a, double b, double plus) {
        if (a == 0 || b == 0) {
            return 0D;
        }
        return a / (b + plus);
    }

    public static double plusSmooth(double a, double b, double plus, double upper) {
        if (a == 0 || b == 0) {
            return 0D;
        }
        double value = a / (b + plus);
        if (value > upper) {
            value = upper + Math.log(value - upper + 1) / 10;
        }
        return value;
    }

    public static double wilsonScore(double click, double exposure) {
        if (exposure <= 0) {
            return 0.0;
        }

        double z = 1.96;
        double ctr = click / exposure;
        if (ctr > 1.0) {
            ctr = 1.0;
        }

        double numerator_1 = ctr + Math.pow(z, 2) / (2 * exposure);
        double numerator_2 = z * Math.sqrt((ctr * (1 - ctr)) / exposure + Math.pow(z / (2 * exposure), 2));
        double denominator = 1.0 + Math.pow(z, 2) / exposure;
        return (numerator_1 - numerator_2) / denominator;
    }

    public static boolean greaterThanZero(double value) {
        return value > 1E-8;
    }

    public static boolean firstLevel(Integer userShareDepth) {
        return null != userShareDepth && 0 == userShareDepth;
    }

    public static String getUserChannel(String rootSourceId) {
        if (null != rootSourceId && !rootSourceId.isEmpty()) {
            for (Map.Entry<String, String[]> entry : userChannelPrefixMap.entrySet()) {
                String channel = entry.getKey();
                String[] prefixArray = entry.getValue();
                if (StringUtils.startsWithAny(rootSourceId, prefixArray)) {
                    return channel;
                }
            }
        }
        return "";
    }

    public static String getResolution(Map<String, String> videoInfo) {
        try {
            if (null != videoInfo && videoInfo.containsKey("width") && videoInfo.containsKey("height")) {
                int width = Integer.parseInt(videoInfo.get("width")) / 100;
                int height = Integer.parseInt(videoInfo.get("height")) / 100;
                return String.format("%d_%d", width, height);
            }
        } catch (Exception ignore) {
        }
        return "";
    }

    public static String extractContent(String data) {
        StringBuilder result = new StringBuilder();
        if (null != data) {
            for (char c : data.toCharArray()) {
                if (isChinese(c) || isDigit(c) || isLetter(c)) {
                    result.append(c);
                }
            }
        }
        return result.toString();
    }

    private static boolean isChinese(char c) {
        return c >= 0x4E00 && c <= 0x9FA5;
    }

    private static boolean isDigit(char c) {
        return c >= '0' && c <= '9';
    }

    private static boolean isLetter(char c) {
        return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
    }

    public static List<String> extractVidsFromUserNetworkSeqFeature(Map<String, String> userNetworkSeqFeature, String key) {
        if (MapUtils.isEmpty(userNetworkSeqFeature) || StringUtils.isBlank(key)) {
            return new ArrayList<>();
        }
        if (!userNetworkSeqFeature.containsKey(key)) {
            return new ArrayList<>();
        }
        String groupSeparator = "\u001D";
        return Arrays.stream(userNetworkSeqFeature.get(key).split(groupSeparator))
                .collect(Collectors.toList());
    }
}
