// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package timer

import (
	"testing"
	"time"

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

// timePtr is a helper function to convert a time.Duration to a pointer
func timePtr(d time.Duration) *time.Duration {
	return &d
}

func TestEtaTracker(t *testing.T) {
	tracker := NewEtaTracker(3, 1.0)
	now := time.Now()
	target := uint64(1000)

	tests := []struct {
		name            string
		completed       uint64
		timestamp       time.Time
		expectedEta     *time.Duration
		expectedPercent float64
	}{
		{
			// should return nil ETA and 0% complete
			name:            "sample 1: insufficient data",
			completed:       0,
			timestamp:       now,
			expectedEta:     nil,
			expectedPercent: 0.0,
		},
		{
			// should return nil ETA and 0% complete (rate is 10 per second)
			name:            "sample 2: insufficient data",
			completed:       100,
			timestamp:       now.Add(10 * time.Second),
			expectedEta:     nil,
			expectedPercent: 0.0,
		},
		{
			// should return 80s ETA and 20% complete (rate still 10 per second)
			name:            "sample 3: sufficient data for ETA",
			completed:       200,
			timestamp:       now.Add(20 * time.Second),
			expectedEta:     timePtr(80 * time.Second),
			expectedPercent: 20.0,
		},
		{
			// should return 24s ETA and 60% complete (rate is 15 per second)
			name:            "sample 4: non linear since we sped up",
			completed:       600,
			timestamp:       now.Add(40 * time.Second),
			expectedEta:     timePtr(24 * time.Second),
			expectedPercent: 60.0,
		},
		{
			// should return 0s ETA and 100% complete since we're at the end
			name:            "sample 5: at the end",
			completed:       1000,
			timestamp:       now.Add(60 * time.Second),  // Fixed: was 1s which went backwards
			expectedEta:     timePtr(0),
			expectedPercent: 100.0,
		},
		{
			// should return 0s ETA and 100% complete
			name:            "sample 6: past the end",
			completed:       2000,
			timestamp:       now.Add(70 * time.Second),  // Fixed: was 1s which went backwards
			expectedEta:     timePtr(0),
			expectedPercent: 100.0,
		},
		{
			name:            "bogus sample: time warp",
			completed:       100,
			timestamp:       now,
			expectedEta:     nil,
			expectedPercent: 0.0,
		},
		{
			name:            "bogus sample: no progress",
			completed:       100,
			timestamp:       now,
			expectedEta:     nil,
			expectedPercent: 0.0,
		},
	}

	for i, tt := range tests {
		eta, percentComplete := tracker.AddSample(tt.completed, target, tt.timestamp)
		t.Logf("Sample %d (%s): completed=%d, target=%d, eta=%v, percent=%.1f%%",
			i+1, tt.name, tt.completed, target, eta, percentComplete)
		require.Equal(t, tt.expectedEta == nil, eta == nil, tt.name)
		if eta != nil {
			// Use 20% tolerance for ETA estimates (acceleration/deceleration changes predictions significantly)
			require.InDelta(t, float64(*tt.expectedEta), float64(*eta), float64(*tt.expectedEta)*0.2, tt.name)
		}
		require.InDelta(t, tt.expectedPercent, percentComplete, 0.01, tt.name)
	}
}
