package org.kne.codec.kif;

import java.text.DecimalFormat;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

/**
 * 通用统计收集器（线程安全）
 * 统计任意对象的出现次数与概率
 * 
 * @param <T> 被统计的对象类型
 */
public class StatisticsCollector<T> {
    
    protected final ConcurrentHashMap<T, AtomicLong> counts = new ConcurrentHashMap<>();
    protected final AtomicLong total = new AtomicLong(0);
    protected final DecimalFormat df = new DecimalFormat("0.00");
    
    /**
     * 记录一次出现
     */
    public void addRecord(T item) {
        counts.computeIfAbsent(item, k -> new AtomicLong(0)).incrementAndGet();
        total.incrementAndGet();
    }
    
    /**
     * 记录多次出现
     */
    public void addRecord(T item, long count) {
        counts.computeIfAbsent(item, k -> new AtomicLong(0)).addAndGet(count);
        total.addAndGet(count);
    }
    
    /**
     * 记录另一个收集器的所有数据
     */
    public void merge(StatisticsCollector<T> other) {
        for (Map.Entry<T, AtomicLong> entry : other.counts.entrySet()) {
            addRecord(entry.getKey(), entry.getValue().get());
        }
    }
    
    /**
     * 获取总次数
     */
    public long getTotal() {
        return total.get();
    }
    
    /**
     * 获取某个对象的出现次数
     */
    public long getCount(T item) {
        AtomicLong count = counts.get(item);
        return count == null ? 0 : count.get();
    }
    
    /**
     * 获取某个对象的出现概率（百分比）
     */
    public double getProbability(T item) {
        long t = total.get();
        if (t == 0) return 0.0;
        return getCount(item) * 100.0 / t;
    }
    
    /**
     * 获取去重对象数量
     */
    public int getUniqueCount() {
        return counts.size();
    }
    
    /**
     * 获取所有对象（按出现次数降序排列）
     */
    public Map<T, AtomicLong> getSorted() {
        return counts.entrySet().stream()
            .sorted((a, b) -> Long.compare(b.getValue().get(), a.getValue().get()))
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue,
                (old, neu) -> old,
                java.util.LinkedHashMap::new
            ));
    }
    
    /**
     * 获取所有对象（按出现次数升序排列）
     */
    public Map<T, AtomicLong> getSortedAscending() {
        return counts.entrySet().stream()
            .sorted((a, b) -> Long.compare(a.getValue().get(), b.getValue().get()))
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue,
                (old, neu) -> old,
                java.util.LinkedHashMap::new
            ));
    }
    
    /**
     * 重置统计
     */
    public void reset() {
        counts.clear();
        total.set(0);
    }
    
    /**
     * 判断是否为空
     */
    public boolean isEmpty() {
        return counts.isEmpty();
    }
    
    /**
     * 生成表格形式的统计报告（需要子类实现格式化）
     */
    public String formatTable(ItemFormatter<T> formatter) {
        long t = total.get();
        if (t == 0) {
            return "（无统计数据）";
        }
        
        StringBuilder sb = new StringBuilder();
        sb.append("╔═══════════════════════════════════════════════════════════════════════════════════╗\n");
        sb.append("║                        统计报告                                                ║\n");
        sb.append("╠═══════════════════════════════════════════════════════════════════════════════════╣\n");
        sb.append("║  序号  │  对象                        │  出现次数  │  占比      │  累积占比     ║\n");
        sb.append("╠═══════════════════════════════════════════════════════════════════════════════════╣\n");
        
        Map<T, AtomicLong> sorted = getSorted();
        long cumulative = 0;
        int index = 0;
        
        for (Map.Entry<T, AtomicLong> entry : sorted.entrySet()) {
            T item = entry.getKey();
            long count = entry.getValue().get();
            double pct = count * 100.0 / t;
            cumulative += count;
            double cumPct = cumulative * 100.0 / t;
            index++;
            
            String itemStr = formatter.format(item);
            // 截断过长的字符串
            if (itemStr.length() > 27) {
                itemStr = itemStr.substring(0, 24) + "...";
            }
            
            sb.append(String.format("║  %4d  │  %-27s  │  %8d  │  %6.2f%%  │  %6.2f%%  ║\n",
                index,
                itemStr,
                count,
                pct,
                cumPct
            ));
        }
        
        sb.append("╠═══════════════════════════════════════════════════════════════════════════════════╣\n");
        sb.append(String.format("║  总次数: %d  │  唯一对象数: %d  │  覆盖率: %6.2f%%                     ║\n",
            t,
            getUniqueCount(),
            100.0
        ));
        sb.append("╚═══════════════════════════════════════════════════════════════════════════════════╝");
        return sb.toString();
    }
    
    /**
     * 生成 CSV 格式报告
     */
    public String toCSV(ItemFormatter<T> formatter) {
        long t = total.get();
        if (t == 0) return "无数据";
        
        StringBuilder sb = new StringBuilder();
        sb.append("序号,对象,次数,占比(%),累积占比(%)\n");
        
        Map<T, AtomicLong> sorted = getSorted();
        long cumulative = 0;
        int index = 0;
        
        for (Map.Entry<T, AtomicLong> entry : sorted.entrySet()) {
            T item = entry.getKey();
            long count = entry.getValue().get();
            double pct = count * 100.0 / t;
            cumulative += count;
            double cumPct = cumulative * 100.0 / t;
            index++;
            
            sb.append(String.format("%d,%s,%d,%.2f,%.2f\n",
                index,
                formatter.format(item),
                count,
                pct,
                cumPct
            ));
        }
        return sb.toString();
    }
    
    @Override
	public String toString() {
		return formatTable((t)->{
			return t.toString();
		});
	}

	/**
     * 对象格式化接口
     */
    public interface ItemFormatter<T> {
        String format(T item);
    }
}