package common

import (
	"testing"
	"time"

	"github.com/stretchr/testify/require"
)

func TestDiskRateCalculator_FirstSampleReturnsNil(t *testing.T) {
	calc := NewDiskRateCalculator()
	rates, err := calc.AddSampleAndComputeRate("pod-0", DiskRateSample{
		Timestamp:  time.Now(),
		TotalIOOps: 1000,
		TotalBytes: 1e9,
	})
	require.NoError(t, err)
	require.Nil(t, rates)
}

func TestDiskRateCalculator_TwoSamplesComputeRate(t *testing.T) {
	calc := NewDiskRateCalculator()
	now := time.Now()

	_, _ = calc.AddSampleAndComputeRate("pod-0", DiskRateSample{
		Timestamp:  now,
		TotalIOOps: 1000,
		TotalBytes: 1e9,
	})

	rates, err := calc.AddSampleAndComputeRate("pod-0", DiskRateSample{
		Timestamp:  now.Add(60 * time.Second),
		TotalIOOps: 7000, // +6000 ops in 60s = 100 IOPS
		TotalBytes: 7e9,  // +6e9 bytes in 60s = 100 MBps
	})
	require.NoError(t, err)
	require.NotNil(t, rates)
	require.InDelta(t, 100, rates.IOPS, 0.01)
	require.InDelta(t, 100, rates.ThroughputMBs, 0.01)
}

func TestDiskRateCalculator_CounterReset(t *testing.T) {
	calc := NewDiskRateCalculator()
	now := time.Now()

	_, _ = calc.AddSampleAndComputeRate("pod-0", DiskRateSample{
		Timestamp:  now,
		TotalIOOps: 5000,
		TotalBytes: 5e9,
	})

	// Counter reset: new values are lower
	rates, err := calc.AddSampleAndComputeRate("pod-0", DiskRateSample{
		Timestamp:  now.Add(60 * time.Second),
		TotalIOOps: 100,
		TotalBytes: 1e6,
	})
	require.NoError(t, err)
	require.Nil(t, rates, "counter reset should return nil rates")
}

func TestDiskRateCalculator_IndependentKeys(t *testing.T) {
	calc := NewDiskRateCalculator()
	now := time.Now()

	// Pod 0: first sample
	_, _ = calc.AddSampleAndComputeRate("pod-0", DiskRateSample{
		Timestamp: now, TotalIOOps: 1000, TotalBytes: 1e9,
	})
	// Pod 1: first sample
	_, _ = calc.AddSampleAndComputeRate("pod-1", DiskRateSample{
		Timestamp: now, TotalIOOps: 2000, TotalBytes: 2e9,
	})

	// Pod 0: second sample
	rates0, err := calc.AddSampleAndComputeRate("pod-0", DiskRateSample{
		Timestamp: now.Add(30 * time.Second), TotalIOOps: 4000, TotalBytes: 4e9,
	})
	require.NoError(t, err)
	require.NotNil(t, rates0)
	require.InDelta(t, 100, rates0.IOPS, 0.01) // 3000/30 = 100

	// Pod 1: second sample
	rates1, err := calc.AddSampleAndComputeRate("pod-1", DiskRateSample{
		Timestamp: now.Add(30 * time.Second), TotalIOOps: 5000, TotalBytes: 8e9,
	})
	require.NoError(t, err)
	require.NotNil(t, rates1)
	require.InDelta(t, 100, rates1.IOPS, 0.01) // 3000/30 = 100
}
