package com.tzld.piaoquan.ad.engine.commons.util;

import org.xm.Similarity;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class ExtractorUtils {

    public static double sigmoid(double x) {
        return 1.0 / (1.0 + Math.exp(-x));
    }

    public static int findInsertPosition(double[] sortedArray, double target) {
        int low = 0;
        int high = sortedArray.length - 1;

        while (low <= high) {
            int mid = low + (high - low) / 2;
            double midValue = sortedArray[mid];

            if (midValue < target) {
                low = mid + 1;
            } else if (midValue > target) {
                high = mid - 1;
            } else {
                // 找到相等的值，尝试在右侧寻找插入点
                while (mid < sortedArray.length - 1 && sortedArray[mid + 1] == target) {
                    mid++;
                }
                return mid + 1; // 返回当前mid的下一个位置作为插入点
            }
        }

        return low; // 返回low作为插入点
    }

    public static Double[] funcC34567ForTags(String tags, String title) {
        String[] tagsList = tags.split(",");
        int d1 = 0;
        List<String> d2 = new ArrayList<>();
        double d3 = 0.0;
        double d4 = 0.0;

        for (String tag : tagsList) {
            if (title.contains(tag)) {
                d1++;
                d2.add(tag);
            }
            double score = Similarity.conceptSimilarity(tag, title);
            if (score > d3) {
                d3 = score;
            }
            d4 += score;
        }

        d4 = (tagsList.length > 0) ? d4 / tagsList.length : d4;

        // 使用数组来返回多个值
        return new Double[]{(double) d1, d3, d4};
    }

    public static Double[] funcC34567ForTagsNew(String tags, String title) {
        return funcC34567ForTagsNewWithCache(tags, title, null);
    }

    /**
     * 优化版本：支持缓存 title 和 tag 的分词结果
     * @param tags 标签字符串，逗号分隔
     * @param title 标题
     * @param titleWords title 的分词结果缓存，如果为 null 则现场分词
     * @param tagWordsCache tag 分词结果缓存（请求级别），可以为 null
     * @return [匹配数量, 最大相似度, 平均相似度]
     */
    public static Double[] funcC34567ForTagsNewWithCache(String tags, String title, List<String> titleWords, Map<String, List<String>> tagWordsCache) {
        if (tags == null || tags.isEmpty() || title == null || title.isEmpty()) {
            return EMPTY_RESULT;
        }

        String[] tagsList = tags.split(",");
        int d1 = 0;
        double d3 = 0.0;
        double d4 = 0.0;

        // 只分词一次 title，复用结果
        List<String> cachedTitleWords = (titleWords != null) ? titleWords : SimilarityUtils.segment(title);

        for (String tag : tagsList) {
            if (tag == null || tag.isEmpty()) {
                continue;
            }
            if (title.contains(tag)) {
                d1++;
            }
            // 使用请求级别的 tag 分词缓存
            List<String> tagWords;
            if (tagWordsCache != null) {
                tagWords = tagWordsCache.computeIfAbsent(tag, SimilarityUtils::segment);
            } else {
                tagWords = SimilarityUtils.segment(tag);
            }
            float score = SimilarityUtils.word2VecSimilarityWithWords(tagWords, cachedTitleWords);
            if (score > d3) {
                d3 = score;
            }
            d4 += score;
        }

        d4 = (tagsList.length > 0) ? d4 / tagsList.length : d4;

        return new Double[]{(double) d1, d3, d4};
    }

    /**
     * 兼容旧接口
     */
    public static Double[] funcC34567ForTagsNewWithCache(String tags, String title, List<String> titleWords) {
        return funcC34567ForTagsNewWithCache(tags, title, titleWords, null);
    }

    /**
     * 空结果常量，避免重复创建数组
     */
    private static final Double[] EMPTY_RESULT = new Double[]{0.0, 0.0, 0.0};

    public static Double calDiv(double a, double b) {
        if (a == 0 || b == 0) {
            return 0D;
        }
        return a / b;
    }

    public static Double calLog(double a) {
        if (a <= 0) {
            return 0D;
        }
        return Math.log(a + 1.0);
    }

    public static Double division(String s1, String s2, Map<String, String> maps) {
        double rate = 0.0;
        if (maps.containsKey(s1) && maps.containsKey(s2)) {
            Double d1 = Double.valueOf(maps.get(s1));
            if (isDoubleEqualToZero(d1)) {
                return rate;
            }
            Double d2 = Double.valueOf(maps.get(s2));
            rate = d2 / d1;
        }
        return rate;
    }

    public static Double divisionDouble(Double d1, Double d2) {
        double rate = 0.0;
        if (isDoubleEqualToZero(d1)) {
            return rate;
        }
        rate = d2 / d1;
        return rate;
    }

    public static boolean isDoubleEqualToZero(double value) {
        final double epsilon = 1e-10; // 定义一个很小的误差范围
        // 判断value是否在误差范围内
        return Math.abs(value) < epsilon;
    }


    public static double calculateVariance(List<Double> numbers) {
        double average = numbers.stream()
                .mapToDouble(Double::doubleValue)
                .average()
                .orElse(0.0);

        double squaredDiffSum = numbers.stream()
                .mapToDouble(Double::doubleValue)
                .map(x -> Math.pow(x - average, 2))
                .average()
                .orElse(0.0);

        return squaredDiffSum;
    }

    public static double calculateAverage(List<Double> numbers) {
        if (numbers == null || numbers.isEmpty()) {
            return 0.0;
        }
        return numbers.stream()
                .mapToDouble(Number::doubleValue)
                .average()
                .orElse(0.0);
    }

    public static List<Double> calculateDifferences(List<Double> numbers) {
        List<Double> differences = new ArrayList<>();

        for (int i = 0; i < numbers.size() - 1; i++) {
            Double diff = 0.0;
            if (!isDoubleEqualToZero(numbers.get(i))) {
                diff = (numbers.get(i + 1) - numbers.get(i)) / numbers.get(i);
            }
            differences.add(diff);
        }

        return differences;
    }

    public static List<String> generateHourStrings(String timeString, int N) {
        LocalDateTime dateTime = LocalDateTime.parse(timeString, DateTimeFormatter.ofPattern("yyyyMMddHH"));
        List<String> hourStrings = new ArrayList<>();
        for (int i = 0; i < N; i++) {
            hourStrings.add(dateTime.minusHours(i).format(DateTimeFormatter.ofPattern("yyyyMMddHH")));
        }

        return hourStrings;
    }

    public static String subtractHours(String inputDateTime, int hoursToSubtract) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHH");
        LocalDateTime dateTime = LocalDateTime.parse(inputDateTime, formatter);
        LocalDateTime subtractedDateTime = dateTime.minusHours(hoursToSubtract);
        return subtractedDateTime.format(formatter);
    }

    // 针对0-1的数字，进行分桶。
    public static Integer ceilLogRate(Double key) {
        double bucket = Math.ceil(
                Math.pow(key, 0.2) * 100
        );
        if (bucket > 300) {
            bucket = 300;
        }
        if (bucket < 0) {
            bucket = 0;
        }
        return (int) bucket;
    }

    // 针对大于1的数字，进行分桶。
    public static int bucketCnt(Double key) {
        long bucket = Math.round(Math.log((key * 10 + 1.0)) * 10);
        if (bucket > 300) {
            bucket = 300;
        }
        if (bucket < 0) {
            bucket = 0;
        }
        return (int) bucket;
    }

    public static void main(String[] args) {
//        System.out.println(ceilLogRate(0.0002));
//        System.out.println(ceilLogRate(0.01));
//        System.out.println(ceilLogRate(0.2));
//        System.out.println(ceilLogRate(4.));
//        System.out.println(bucketCnt(1.));
//        System.out.println(bucketCnt(20.));
//        System.out.println(bucketCnt(500.));
//        System.out.println(bucketCnt(50000.));

        System.out.println(generateHourStrings("2024011603", 5));

    }

}
