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/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(10 * time.Minute)

	tests := []struct {
		name     string
		input    PricedProcessingResource
		expected float64
	}{
		{
			name: "Nil start time, non-service",
			input: PricedProcessingResource{
				PricedResource: PricedResource[*ProcessingResourcePricingProfile]{
					BookingConfiguration: &resources.BookingConfiguration{
						UsageStart: nil,
					},
				},
			},
			expected: float64((5 * time.Minute).Seconds()),
		},
		{
			name: "Duration computed from start and end",
			input: PricedProcessingResource{
				PricedResource: PricedResource[*ProcessingResourcePricingProfile]{
					BookingConfiguration: &resources.BookingConfiguration{
						UsageStart: &now,
						UsageEnd:   &after,
					},
				},
			},
			expected: float64((10 * time.Minute).Seconds()),
		},
		{
			name: "Explicit duration takes precedence",
			input: PricedProcessingResource{
				PricedResource: PricedResource[*ProcessingResourcePricingProfile]{
					BookingConfiguration: &resources.BookingConfiguration{
						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_GetPriceHT(t *testing.T) {
	start := time.Now()
	end := start.Add(10 * time.Minute)
	mockPricing := pricing.AccessPricingProfile[pricing.TimePricingStrategy]{
		Pricing: pricing.PricingStrategy[pricing.TimePricingStrategy]{
			Price: 100.0,
		},
	}
	profile := &ProcessingResourcePricingProfile{AccessPricingProfile: mockPricing}
	price, err := profile.GetPriceHT(1, 0, start, end, []*pricing.PricingVariation{})
	assert.NoError(t, err)
	assert.Equal(t, 100.0, price)
}

func TestProcessingResourcePricingProfile_IsPurchased(t *testing.T) {
	purchased := &ProcessingResourcePricingProfile{
		AccessPricingProfile: pricing.AccessPricingProfile[pricing.TimePricingStrategy]{
			Pricing: pricing.PricingStrategy[pricing.TimePricingStrategy]{
				BuyingStrategy: pricing.PERMANENT,
			},
		},
	}
	assert.True(t, purchased.IsPurchasable())
}
