package cmek

import (
	"google.golang.org/protobuf/types/known/timestamppb"
	"gorm.io/gorm"

	globalcommonv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/common/v1"
	globaldedicatedv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/dedicated/v1"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/entity"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/infra/repoimpl/schema"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
	"github.com/tidbcloud/tidb-management-service/utilities/enum"
)

func cvtCmekModel(
	en *entity.CustomerManagedEncryptionKey,
	regionId, providerId uint64,
) (*schema.CustomerManagedEncryptionKey, bizerr.BizError) {
	if en == nil {
		return nil, bizerr.New(bizerr.ErrCodeParams, "customer managed encryption key is invalid")
	}
	cmek := &schema.CustomerManagedEncryptionKey{
		Model: gorm.Model{
			ID: uint(en.GetId()),
		},
		TenantId:   en.OrganizationId,
		ProjectId:  en.ProjectId,
		RegionId:   regionId,
		ProviderId: providerId,
	}

	switch en.CloudProviderId {
	case globalcommonv1.CloudProvider_AWS:
		cmek.MasterKey = en.GetAwsKeyArn()
	case globalcommonv1.CloudProvider_GCP:
		cmek.MasterKey = en.GetGcpKeyName()
	case globalcommonv1.CloudProvider_AZURE:
		cmek.MasterKey = en.GetAzureKeyVault().GetKeyVaultKey()
		cmek.AzureKeyVaultName = en.GetAzureKeyVault().GetKeyVaultName()
		cmek.AzureAppRegistrationId = en.GetAzureKeyVault().GetAzureAppRegistration().GetAppRegistrationId()
		cmek.AzureAppRegistrationUmi = en.GetAzureKeyVault().GetAzureAppRegistration().GetAppRegistrationUmi()
		cmek.AzureAppRegistrationName = en.GetAzureKeyVault().GetAzureAppRegistration().GetAppRegistrationName()

	default:
		return nil, bizerr.New(bizerr.ErrCodeParams, "invalid cloud provider")
	}

	return cmek, nil
}

func cvtCmekEntity(model *schema.CustomerManagedEncryptionKey) (*entity.CustomerManagedEncryptionKey, bizerr.BizError) {
	if model == nil {
		return nil, bizerr.New(bizerr.ErrCodeUnknown, "cmek schema is nil")
	}

	region, err := enum.FromString[globalcommonv1.Region_Name](model.Region.RegionName)
	if err != nil {
		return nil, bizerr.New(bizerr.ErrCodeParams, "invalid region")
	}

	provider, err := enum.FromString[globalcommonv1.CloudProvider_Name](model.Provider.Name)
	if err != nil {
		return nil, bizerr.New(bizerr.ErrCodeParams, "invalid cloud provider")
	}

	en := &entity.CustomerManagedEncryptionKey{
		Id:                uint64(model.ID),
		OrganizationId:    model.TenantId,
		ProjectId:         model.ProjectId,
		RegionId:          entity.RegionName(region),
		RegionDisplayName: model.Region.DisplayName,
		CloudProviderId:   entity.CloudProviderName(provider),
		CreateTime:        timestamppb.New(model.CreatedAt),
		UpdateTime:        timestamppb.New(model.UpdatedAt),
	}

	switch en.CloudProviderId {
	case globalcommonv1.CloudProvider_AWS:
		en.MasterKey = &globaldedicatedv1.CustomerManagedEncryptionKey_AwsKeyArn{
			AwsKeyArn: model.MasterKey,
		}
	case globalcommonv1.CloudProvider_GCP:
		en.MasterKey = &globaldedicatedv1.CustomerManagedEncryptionKey_GcpKeyName{
			GcpKeyName: model.MasterKey,
		}
	case globalcommonv1.CloudProvider_AZURE:
		en.MasterKey = &globaldedicatedv1.CustomerManagedEncryptionKey_AzureKeyVault{
			AzureKeyVault: &globaldedicatedv1.AzureKeyVault{
				KeyVaultKey:  model.MasterKey,
				KeyVaultName: model.AzureKeyVaultName,
				AzureAppRegistration: &globaldedicatedv1.AzureAppRegistration{
					AppRegistrationId:   model.AzureAppRegistrationId,
					AppRegistrationUmi:  model.AzureAppRegistrationUmi,
					AppRegistrationName: model.AzureAppRegistrationName,
				},
			},
		}
	default:
		return nil, bizerr.New(bizerr.ErrCodeParams, "invalid cloud provider")
	}

	if model.DeletedAt.Valid {
		en.DeleteTime = timestamppb.New(model.DeletedAt.Time)
	} else {
		en.DeleteTime = nil
	}

	return en, nil
}
