package resources_test

import (
	"testing"
	"time"

	"cloud.o-forge.io/core/oc-lib/models/common/pricing"
	. "cloud.o-forge.io/core/oc-lib/models/resources"
	"cloud.o-forge.io/core/oc-lib/tools"
	"github.com/stretchr/testify/assert"
)

func TestProcessingResource_GetType(t *testing.T) {
	r := &ProcessingResource{}
	assert.Equal(t, tools.PROCESSING_RESOURCE.String(), r.GetType())
}

func TestPricedProcessingResource_GetType(t *testing.T) {
	r := &PricedProcessingResource{}
	assert.Equal(t, tools.PROCESSING_RESOURCE, r.GetType())
}

func TestPricedProcessingResource_GetExplicitDurationInS(t *testing.T) {
	now := time.Now()
	after := now.Add(2 * time.Hour)

	tests := []struct {
		name     string
		input    PricedProcessingResource
		expected float64
	}{
		{
			name: "Service without explicit duration",
			input: PricedProcessingResource{
				IsService: true,
			},
			expected: -1,
		},
		{
			name: "Nil start time, non-service",
			input: PricedProcessingResource{
				PricedResource: PricedResource{
					UsageStart: nil,
				},
			},
			expected: float64((1 * time.Hour).Seconds()),
		},
		{
			name: "Duration computed from start and end",
			input: PricedProcessingResource{
				PricedResource: PricedResource{
					UsageStart: &now,
					UsageEnd:   &after,
				},
			},
			expected: float64((2 * time.Hour).Seconds()),
		},
		{
			name: "Explicit duration takes precedence",
			input: PricedProcessingResource{
				PricedResource: PricedResource{
					ExplicitBookingDurationS: 1337,
				},
			},
			expected: 1337,
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			assert.Equal(t, test.expected, test.input.GetExplicitDurationInS())
		})
	}
}

func TestProcessingResource_GetAccessor(t *testing.T) {
	request := &tools.APIRequest{}
	r := &ProcessingResource{}
	acc := r.GetAccessor(request)
	assert.NotNil(t, acc)
}

func TestProcessingResourcePricingProfile_GetPrice(t *testing.T) {
	start := time.Now()
	end := start.Add(2 * time.Hour)
	mockPricing := pricing.AccessPricingProfile[pricing.TimePricingStrategy]{
		Pricing: pricing.PricingStrategy[pricing.TimePricingStrategy]{
			Price: 100.0,
		},
	}
	profile := &ProcessingResourcePricingProfile{mockPricing}
	price, err := profile.GetPrice(0, 0, start, end)
	assert.NoError(t, err)
	assert.Equal(t, 100.0, price)
}

func TestProcessingResourcePricingProfile_IsPurchased(t *testing.T) {
	nonPurchased := &ProcessingResourcePricingProfile{
		AccessPricingProfile: pricing.AccessPricingProfile[pricing.TimePricingStrategy]{
			Pricing: pricing.PricingStrategy[pricing.TimePricingStrategy]{
				BuyingStrategy: pricing.PAY_PER_USE,
			},
		},
	}
	assert.False(t, nonPurchased.IsPurchased())

	purchased := &ProcessingResourcePricingProfile{
		AccessPricingProfile: pricing.AccessPricingProfile[pricing.TimePricingStrategy]{
			Pricing: pricing.PricingStrategy[pricing.TimePricingStrategy]{
				BuyingStrategy: pricing.UNLIMITED,
			},
		},
	}
	assert.True(t, purchased.IsPurchased())
}