package recovery

import (
	"testing"
	"time"

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

func TestDefaultRetryPolicy(t *testing.T) {
	policy := DefaultRetryPolicy()
	assert.NotNil(t, policy)
	assert.Equal(t, time.Second, policy.InitialInterval)
	assert.Equal(t, time.Minute, policy.MaximumInterval)
	assert.Equal(t, 2.0, policy.BackoffCoefficient)
	assert.Equal(t, int32(5), policy.MaximumAttempts)
}

func TestActivityRetryPolicy(t *testing.T) {
	policy := ActivityRetryPolicy()
	assert.NotNil(t, policy)
	assert.Equal(t, 2*time.Second, policy.InitialInterval)
	assert.Equal(t, 5*time.Minute, policy.MaximumInterval)
	assert.Equal(t, 2.0, policy.BackoffCoefficient)
	assert.Equal(t, int32(3), policy.MaximumAttempts)
}

func TestLLMActivityRetryPolicy(t *testing.T) {
	policy := LLMActivityRetryPolicy()
	assert.NotNil(t, policy)
	assert.Equal(t, 5*time.Second, policy.InitialInterval)
	assert.Equal(t, 10*time.Minute, policy.MaximumInterval)
	assert.Equal(t, 1.5, policy.BackoffCoefficient)
	assert.Equal(t, int32(5), policy.MaximumAttempts)
}

func TestToTemporalRetryPolicy(t *testing.T) {
	policy := DefaultRetryPolicy()
	temporal := policy.ToTemporalRetryPolicy()
	assert.NotNil(t, temporal)
	assert.Equal(t, time.Second, temporal.InitialInterval)
	assert.Equal(t, time.Minute, temporal.MaximumInterval)
	assert.Equal(t, 2.0, temporal.BackoffCoefficient)
	assert.Equal(t, int32(5), temporal.MaximumAttempts)
}

func TestNilRetryPolicyToTemporal(t *testing.T) {
	var policy *RetryPolicy
	temporal := policy.ToTemporalRetryPolicy()
	assert.Nil(t, temporal)
}

func TestIsRetryableError(t *testing.T) {
	// Nil error is not retryable
	assert.False(t, IsRetryableError(nil))

	// Generic errors are retryable
	assert.True(t, IsRetryableError(assert.AnError))
}

func TestRetryCount(t *testing.T) {
	rc := RetryCount{Current: 0, Maximum: 3}

	assert.True(t, rc.CanRetry())

	rc.Increment()
	assert.Equal(t, 1, rc.Current)
	assert.True(t, rc.CanRetry())

	rc.Increment()
	rc.Increment()
	assert.Equal(t, 3, rc.Current)
	assert.False(t, rc.CanRetry())
}

func TestRetryCountUnlimited(t *testing.T) {
	rc := RetryCount{Current: 100, Maximum: 0}
	assert.True(t, rc.CanRetry())

	rc.Increment()
	assert.True(t, rc.CanRetry())
}
