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"
	"github.com/stretchr/testify/require"
)

func TestDataResource_GetType(t *testing.T) {
	d := &resources.DataResource{}
	assert.Equal(t, tools.DATA_RESOURCE.String(), d.GetType())
}

func TestDataResource_GetAccessor(t *testing.T) {
	req := &tools.APIRequest{}
	acc := (&resources.DataResource{}).GetAccessor(req)
	assert.NotNil(t, acc)
}

func TestDataResource_ConvertToPricedResource(t *testing.T) {
	d := &resources.DataResource{}
	d.UUID = "123"
	res, _ := d.ConvertToPricedResource(tools.DATA_RESOURCE, nil, nil, nil, nil, nil, &tools.APIRequest{})
	assert.IsType(t, &resources.PricedDataResource{}, res)

	nilRes, _ := d.ConvertToPricedResource(tools.PROCESSING_RESOURCE, nil, nil, nil, nil, nil, &tools.APIRequest{})
	assert.Nil(t, nilRes)
}

func TestDataResourcePricingStrategy_GetQuantity(t *testing.T) {
	tests := []struct {
		strategy resources.DataResourcePricingStrategy
		input    float64
		expected float64
	}{
		{resources.PER_DOWNLOAD, 1, 1},
		{resources.PER_TB_DOWNLOADED, 1, 1000},
		{resources.PER_GB_DOWNLOADED, 2.5, 2.5},
		{resources.PER_MB_DOWNLOADED, 1, 0.001},
		{resources.PER_KB_DOWNLOADED, 1, 0.000001},
	}

	for _, tt := range tests {
		q, err := tt.strategy.GetQuantity(tt.input)
		require.NoError(t, err)
		assert.InDelta(t, tt.expected, q, 1e-9)
	}

	_, err := resources.DataResourcePricingStrategy(999).GetQuantity(1)
	assert.Error(t, err)
}

func TestDataResourcePricingProfile_IsPurchased(t *testing.T) {
	profile := &resources.DataResourcePricingProfile{}
	profile.Pricing.BuyingStrategy = pricing.PERMANENT
	assert.True(t, profile.IsPurchasable())
}

func TestPricedDataResource_GetPriceHT(t *testing.T) {
	now := time.Now()
	later := now.Add(5 * time.Minute)
	mockPrice := 42.0

	pricingProfile := &resources.DataResourcePricingProfile{AccessPricingProfile: pricing.AccessPricingProfile[resources.DataResourcePricingStrategy]{
		Pricing: pricing.PricingStrategy[resources.DataResourcePricingStrategy]{Price: 42.0}},
	}
	pricingProfile.Pricing.OverrideStrategy = resources.PER_GB_DOWNLOADED

	r := &resources.PricedDataResource{
		PricedResource: resources.PricedResource[*resources.DataResourcePricingProfile]{
			SelectedPricing: pricingProfile,
			BookingConfiguration: &resources.BookingConfiguration{
				UsageStart: &now,
				UsageEnd:   &later,
			},
		},
	}

	price, err := r.GetPriceHT()
	require.NoError(t, err)
	assert.Equal(t, mockPrice, price)
}

func TestPricedDataResource_GetPriceHT_NoProfiles(t *testing.T) {
	r := &resources.PricedDataResource{
		PricedResource: resources.PricedResource[*resources.DataResourcePricingProfile]{
			ResourceID: "test-resource",
		},
	}
	_, err := r.GetPriceHT()
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "pricing profile must be set")
}

func TestPricedDataResource_GetType(t *testing.T) {
	r := &resources.PricedDataResource{}
	assert.Equal(t, tools.DATA_RESOURCE, r.GetType())
}
