package common

import (
	"reflect"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"google.golang.org/protobuf/proto"

	globalcommonv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/common/v1"
	globalngv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/nextgen/v1"
	openapicommonv1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/common/v1beta1"
	openapingv1beta2 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/nextgen/v1beta2"
)

func TestConvertToOpenapiBackups(t *testing.T) {
	backups := ConvertToOpenapiBackups([]*globalngv1.Backup{
		{
			Id:              "backup-1",
			ClusterId:       "cluster-1",
			OrganizationId:  "org-1",
			ServicePlan:     globalcommonv1.ServicePlan_Premium,
			DisplayName:     "backup name",
			Description:     "backup desc",
			Size:            1024,
			State:           globalngv1.Backup_STATE_SUCCESS,
			Type:            globalngv1.Backup_TYPE_SNAPSHOT,
			TriggerType:     globalngv1.Backup_TRIGGER_TYPE_MANUAL,
			BackupTs:        "456",
			RegionId:        "AWS_US_WEST_2",
			CustomerManaged: true,
			EncryptionKeyId: 99,
		},
	})

	require.Len(t, backups, 1)

	encryptionKeyField, ok := reflect.TypeFor[openapingv1beta2.Backup]().FieldByName("EncryptionKeyId")
	require.True(t, ok)
	assert.Equal(t, reflect.String, encryptionKeyField.Type.Kind())

	encryptionKeyValue := reflect.ValueOf(backups[0]).Elem().FieldByName("EncryptionKeyId")
	require.True(t, encryptionKeyValue.IsValid())
	assert.Equal(t, "99", encryptionKeyValue.String())

	assert.Equal(t, &openapingv1beta2.Backup{
		Id:              "backup-1",
		TidbId:          "cluster-1",
		OrganizationId:  "org-1",
		ServicePlan:     openapicommonv1beta1.ServicePlan_Premium,
		DisplayName:     "backup name",
		Description:     "backup desc",
		SizeBytes:       1024,
		State:           openapingv1beta2.Backup_SUCCEEDED,
		Type:            openapingv1beta2.Backup_SNAPSHOT,
		TriggerType:     openapingv1beta2.Backup_MANUAL,
		BackupTs:        "456",
		RegionId:        "aws-us-west-2",
		CustomerManaged: true,
		EncryptionKeyId: "99",
	}, backups[0])
}

func TestConvertBackupServicePlansByName(t *testing.T) {
	backups := ConvertToOpenapiBackups([]*globalngv1.Backup{
		{ServicePlan: globalcommonv1.ServicePlan_Essential_V2},
		{ServicePlan: globalcommonv1.ServicePlan_Premium_Reserved},
	})

	require.Len(t, backups, 2)
	assert.Equal(t, openapicommonv1beta1.ServicePlan_Essential_V2, backups[0].ServicePlan)
	assert.Equal(t, openapicommonv1beta1.ServicePlan_Premium_Reserved, backups[1].ServicePlan)

	assert.Equal(t, []globalcommonv1.ServicePlan{
		globalcommonv1.ServicePlan_Essential_V2,
		globalcommonv1.ServicePlan_Premium_Reserved,
	}, ConvertToNextgenServicePlans([]openapicommonv1beta1.ServicePlan{
		openapicommonv1beta1.ServicePlan_Essential_V2,
		openapicommonv1beta1.ServicePlan_Premium_Reserved,
	}))
}

func TestConvertToOpenapiBackupSetting(t *testing.T) {
	result := ConvertToOpenapiBackupSetting(&globalngv1.BackupSetting{
		ClusterId:          "123",
		BackupPolicy:       globalngv1.BackupSetting_BackupPolicy_TIER1,
		Mode:               globalngv1.BackupSetting_FLEXIBLE_RETENTION,
		RetentionDays:      proto.Int32(20),
		DailyBackupTimeUtc: proto.String("08:30"),
	})

	require.Equal(t, "123", result.TidbId)
	require.Equal(t, openapingv1beta2.BackupSetting_BackupPolicy_TIER1, result.BackupPolicy)
	require.Equal(t, openapingv1beta2.BackupSetting_FLEXIBLE_RETENTION, result.Mode)
	require.Equal(t, int32(20), result.GetRetentionDays())
	require.Equal(t, "08:30", result.GetDailyBackupTimeUtc())
}
