package org.kne.cloud.network.monitor;

import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;

/**
 * 高性能网络延迟统计器
 * 
 * 设计要点：
 * 1. 数据面使用 LongAdder 无锁累加总延迟，同时用 AtomicLong 原子记录最值。
 * 2. 控制面使用快照缓存，计算平均延迟、最小延迟、最大延迟和抖动。
 * 3. 采样方式支持：每包采样（高频）或每N包采样（低频），避免测量本身成为开销。
 */
public class DelaySampler {

    // 数据面累加器（用于计算平均延迟）
    private final LongAdder totalDelayNanos = new LongAdder();
    private final LongAdder packetCount = new LongAdder();
    
    // 最值记录（使用 AtomicLong，保证原子更新，彻底避免读到中间状态）
    private final AtomicLong minDelayNanos = new AtomicLong(Long.MAX_VALUE);
    private final AtomicLong maxDelayNanos = new AtomicLong(0);
    
    // 快照缓存（控制面使用）
    private volatile long snapshotTotalDelay = 0;
    private volatile long snapshotPacketCount = 0;
    private volatile long snapshotMinDelay = 0;
    private volatile long snapshotMaxDelay = 0;
    private volatile long lastSnapshotTime = 0;
    private volatile long currentAvgDelayNanos = 0;
    private volatile long currentMinDelayNanos = 0;
    private volatile long currentMaxDelayNanos = 0;
    private volatile long currentJitterNanos = 0;  // 抖动：平均绝对偏差（基于相邻包延迟差）
    
    // 可选：用于计算抖动的历史延迟总和（或保留上次延迟值）
    private volatile long lastDelayNanos = 0;
    private final LongAdder jitterSumAbs = new LongAdder();  // 绝对偏差累积和（|delay_i - delay_{i-1}|）
    
    /**
     * 数据面调用：记录一个包的延迟（纳秒）
     * @param delayNanos 延迟（纳秒）
     */
    public void recordDelay(long delayNanos) {
        packetCount.increment();
        totalDelayNanos.add(delayNanos);
        
        // 更新最值（无锁自旋 CAS，线程安全）
        updateMin(delayNanos);
        updateMax(delayNanos);
        
        // 更新抖动：记录本次延迟与上次的差值绝对值
        long last = lastDelayNanos;
        if (last != 0) {
            jitterSumAbs.add(Math.abs(delayNanos - last));
        }
        lastDelayNanos = delayNanos;
    }
    
    /**
     * 更新最小值（无锁 CAS 自旋）
     */
    private void updateMin(long delayNanos) {
        long min;
        do {
            min = minDelayNanos.get();
            if (delayNanos >= min) {
                return; // 不是新最小值，直接返回
            }
        } while (!minDelayNanos.compareAndSet(min, delayNanos));
    }
    
    /**
     * 更新最大值（无锁 CAS 自旋）
     */
    private void updateMax(long delayNanos) {
        long max;
        do {
            max = maxDelayNanos.get();
            if (delayNanos <= max) {
                return; // 不是新最大值，直接返回
            }
        } while (!maxDelayNanos.compareAndSet(max, delayNanos));
    }
    
    /**
     * 控制面调用：更新统计快照（建议与 BandwidthSampler.update() 同频调用）
     * 计算平均延迟、最小延迟、最大延迟、抖动，并重置累加器
     */
    public void update() {
        long now = System.nanoTime();
        
        // 取当前累加值并重置
        long currPackets = packetCount.sumThenReset();
        long currTotalDelay = totalDelayNanos.sumThenReset();
        long currJitterSum = jitterSumAbs.sumThenReset();
        
        // 取当前最值并重置（重置为初始值）
        long currMin = minDelayNanos.getAndSet(Long.MAX_VALUE);
        long currMax = maxDelayNanos.getAndSet(0);
        
        // 更新时间间隔（秒）
        double intervalSec = (lastSnapshotTime == 0) ? 1.0 : (now - lastSnapshotTime) / 1_000_000_000.0;
        if (intervalSec <= 0) intervalSec = 1.0;
        
        // 更新快照缓存
        snapshotPacketCount = currPackets;
        snapshotTotalDelay = currTotalDelay;
        snapshotMinDelay = currMin;
        snapshotMaxDelay = currMax;
        
        // 计算统计指标
        if (currPackets > 0) {
            currentAvgDelayNanos = (long) ((double) currTotalDelay / currPackets);
            currentMinDelayNanos = currMin;
            currentMaxDelayNanos = currMax;
            
            // 抖动：平均绝对偏差（MAD） = 累积绝对偏差 / (包数 - 1)
            if (currJitterSum > 0 && currPackets > 1) {
                currentJitterNanos = (long) ((double) currJitterSum / (currPackets - 1));
            } else {
                currentJitterNanos = 0;
            }
        } else {
            currentAvgDelayNanos = 0;
            currentMinDelayNanos = 0;
            currentMaxDelayNanos = 0;
            currentJitterNanos = 0;
        }
        
        // 重置 lastDelay，避免跨间隔的抖动误差
        lastDelayNanos = 0;
        
        lastSnapshotTime = now;
    }
    
    // ========== 查询接口（直接返回缓存，无计算开销）==========
    public long getAvgDelayNanos() {
        return currentAvgDelayNanos;
    }
    
    public long getMinDelayNanos() {
        return currentMinDelayNanos;
    }
    
    public long getMaxDelayNanos() {
        return currentMaxDelayNanos;
    }
    
    public long getJitterNanos() {
        return currentJitterNanos;
    }
    
    public long getSnapshotPacketCount() {
        return snapshotPacketCount;
    }
    
    public long getSnapshotTotalDelay() {
        return snapshotTotalDelay;
    }
}