package com.ruoyi.web.modules.openstats.support;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.stereotype.Component;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.modules.openstats.constant.OpenStatsConstants;
import com.ruoyi.web.modules.openstats.vo.ReviewWordCloudVO;
import com.ruoyi.web.modules.openstats.vo.WordCloudItemVO;

/**
 * 评价正文分词 + 停用词过滤 + Top50
 */
@Component
public class ReviewWordCloudSupport
{
    private static final Pattern CHINESE_RUN = Pattern.compile("[\\u4e00-\\u9fa5]{2,}");

    private static final Pattern NON_WORD = Pattern.compile("[\\p{Punct}\\s\\d]+");

    private volatile Set<String> stopWords;

    public ReviewWordCloudVO buildTopWords(List<String> contents)
    {
        Map<String, Long> freq = new HashMap<>();
        if (contents != null)
        {
            for (String content : contents)
            {
                collectWords(content, freq);
            }
        }
        List<Map.Entry<String, Long>> entries = new ArrayList<>(freq.entrySet());
        entries.sort(Comparator.<Map.Entry<String, Long>>comparingLong(Map.Entry::getValue).reversed()
                .thenComparing(Map.Entry::getKey));
        ReviewWordCloudVO vo = new ReviewWordCloudVO();
        int limit = Math.min(OpenStatsConstants.WORD_CLOUD_LIMIT, entries.size());
        for (int i = 0; i < limit; i++)
        {
            Map.Entry<String, Long> entry = entries.get(i);
            WordCloudItemVO item = new WordCloudItemVO();
            item.setWord(entry.getKey());
            item.setCount(entry.getValue());
            vo.getItems().add(item);
        }
        return vo;
    }

    private void collectWords(String content, Map<String, Long> freq)
    {
        if (StringUtils.isEmpty(content))
        {
            return;
        }
        String normalized = NON_WORD.matcher(content.trim()).replaceAll("");
        Matcher matcher = CHINESE_RUN.matcher(normalized);
        Set<String> stopWordSet = loadStopWords();
        while (matcher.find())
        {
            String run = matcher.group();
            emitTokens(run, stopWordSet, freq);
        }
    }

    private void emitTokens(String run, Set<String> stopWordSet, Map<String, Long> freq)
    {
        if (run.length() <= 4)
        {
            addToken(run, stopWordSet, freq);
            return;
        }
        for (int len = 2; len <= 3; len++)
        {
            for (int i = 0; i <= run.length() - len; i++)
            {
                addToken(run.substring(i, i + len), stopWordSet, freq);
            }
        }
    }

    private void addToken(String token, Set<String> stopWordSet, Map<String, Long> freq)
    {
        if (StringUtils.isEmpty(token) || token.length() < 2 || stopWordSet.contains(token))
        {
            return;
        }
        freq.merge(token, 1L, Long::sum);
    }

    private Set<String> loadStopWords()
    {
        Set<String> cached = stopWords;
        if (cached != null)
        {
            return cached;
        }
        synchronized (this)
        {
            if (stopWords != null)
            {
                return stopWords;
            }
            Set<String> loaded = new HashSet<>();
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(
                    ReviewWordCloudSupport.class.getResourceAsStream("/openstats/stopwords.txt"),
                    StandardCharsets.UTF_8)))
            {
                String line;
                while ((line = reader.readLine()) != null)
                {
                    line = line.trim();
                    if (!line.isEmpty() && !line.startsWith("#"))
                    {
                        loaded.add(line);
                    }
                }
            }
            catch (Exception ex)
            {
                loaded.addAll(defaultStopWords());
            }
            stopWords = Collections.unmodifiableSet(loaded);
            return stopWords;
        }
    }

    private Set<String> defaultStopWords()
    {
        Set<String> defaults = new HashSet<>();
        Collections.addAll(defaults, "的", "了", "是", "我", "很", "好", "也", "就", "都", "还", "在",
                "有", "和", "与", "及", "或", "一个", "这个", "那个", "什么", "怎么", "非常", "比较",
                "感觉", "真的", "还是", "已经", "没有", "不是", "可以", "觉得", "购买", "收到", "商品",
                "不错", "满意", "推荐", "物流", "快递", "包装", "质量", "服务", "卖家", "店铺");
        return defaults;
    }
}
