package tests

import (
	"context"
	"errors"
	"testing"
	"time"

	"github.com/jfraeys/fetch_ml/internal/network"
)

func TestRetry_Success(t *testing.T) {
	t.Parallel() // Enable parallel execution
	ctx := context.Background()
	cfg := network.DefaultRetryConfig()
	attempts := 0

	err := network.Retry(ctx, cfg, func() error {
		attempts++
		if attempts < 2 {
			return errors.New("temporary failure")
		}
		return nil
	})

	if err != nil {
		t.Errorf("Expected success, got error: %v", err)
	}

	if attempts != 2 {
		t.Errorf("Expected 2 attempts, got %d", attempts)
	}
}

func TestRetry_MaxAttempts(t *testing.T) {
	t.Parallel() // Enable parallel execution
	ctx := context.Background()
	cfg := network.RetryConfig{
		MaxAttempts:  3,
		InitialDelay: 10 * time.Millisecond,
		MaxDelay:     100 * time.Millisecond,
		Multiplier:   2.0,
	}
	attempts := 0

	err := network.Retry(ctx, cfg, func() error {
		attempts++
		return errors.New("always fails")
	})

	if err == nil {
		t.Error("Expected error after max attempts")
	}

	if attempts != 3 {
		t.Errorf("Expected 3 attempts, got %d", attempts)
	}
}

func TestRetry_ContextCancellation(t *testing.T) {
	t.Parallel() // Enable parallel execution
	ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
	defer cancel()

	cfg := network.DefaultRetryConfig()
	attempts := 0

	err := network.Retry(ctx, cfg, func() error {
		attempts++
		time.Sleep(20 * time.Millisecond) // Simulate work
		return errors.New("always fails")
	})

	if err != context.DeadlineExceeded {
		t.Errorf("Expected context deadline exceeded, got: %v", err)
	}

	// Should have attempted at least once but not all attempts due to timeout
	if attempts == 0 {
		t.Error("Expected at least one attempt")
	}
}

func TestRetryWithBackoff(t *testing.T) {
	t.Parallel() // Enable parallel execution
	ctx := context.Background()
	attempts := 0

	err := network.RetryWithBackoff(ctx, 3, func() error {
		attempts++
		if attempts < 3 {
			return errors.New("temporary failure")
		}
		return nil
	})

	if err != nil {
		t.Errorf("Expected success, got error: %v", err)
	}

	if attempts != 3 {
		t.Errorf("Expected 3 attempts, got %d", attempts)
	}
}

func TestRetryForNetworkOperations(t *testing.T) {
	t.Parallel() // Enable parallel execution
	ctx := context.Background()
	attempts := 0

	err := network.RetryForNetworkOperations(ctx, func() error {
		attempts++
		if attempts < 5 {
			return errors.New("network error")
		}
		return nil
	})

	if err != nil {
		t.Errorf("Expected success, got error: %v", err)
	}

	if attempts != 5 {
		t.Errorf("Expected 5 attempts, got %d", attempts)
	}
}
