package domain

import (
	"fmt"
	"time"

	"github.com/tidbcloud/dataflow-service/app/repo/entity"
	dfs3 "github.com/tidbcloud/dataflow-service/pkg/aws"
)

type BucketAction string

const (
	CreateBucket           BucketAction = "create"
	EditBucket             BucketAction = "edit"
	DeleteBucket           BucketAction = "delete"
	EditBucketPolicy       BucketAction = "edit_bucket_policy"
	EditBucketReplications BucketAction = "edit_bucket_replications"
)

type CreateBucketReqV2 struct {
	BusinessPurpose *BucketBusinessPurpose
	Scope           *entity.BucketScope

	TenantId       *uint64
	ProjectId      *uint64
	ClusterId      *uint64
	CloudAccountID *string

	Name               *string
	Description        *string
	InfraCloudProvider *InfraProviderType
	Regions            []string
}

type BucketBusinessPurpose string

const (
	BucketBusinessPurposeDefault       BucketBusinessPurpose = "default"
	BucketBusinessPurposeDualRegion    BucketBusinessPurpose = "dual-region"
	BucketBusinessPurposeRecoveryGroup BucketBusinessPurpose = "recovery-group"
)

type CreateBucketRespV2 struct {
	BucketID   uint64
	Status     entity.BucketStatus
	WorkflowID *string
}

type DeleteBucketReqV2 struct {
	BucketID           *uint64
	InfraCloudProvider *InfraProviderType
}

type DeleteBucketRespV2 struct {
	WorkflowID *string
}

type GetBucketReq struct {
	BucketID           uint64
	InfraCloudProvider *InfraProviderType
}

type GetBucketResp struct {
	Bucket *entity.Bucket
}

type GrantAccessToBucketReq struct {
	BucketID *uint64
	// CloudProviderIdentities for AWS, they are iam roles; for GCP, they are service accounts
	CloudProviderIdentities []string
	InfraCloudProvider      *InfraProviderType
}

type GrantAccessToBucketResp struct{}

type RevokeAccessToBucketReq struct {
	BucketID *uint64
	// CloudProviderIdentities for AWS, they are iam roles; for GCP, they are service accounts
	CloudProviderIdentities []string
	InfraCloudProvider      *InfraProviderType
}

type RevokeAccessToBucketResp struct{}

type CreateBucketReplicationReq struct {
	SourceBucketID *uint64
	TargetBucketID *uint64
	ClusterID      *uint64

	ReplicationPrefix  *string
	InfraCloudProvider *InfraProviderType
}

type CreateBucketReplicationResp struct{}

type DeleteBucketReplicationReq struct {
	SourceBucketID *uint64
	TargetBucketID *uint64

	ReplicationPrefix  *string
	InfraCloudProvider *InfraProviderType
}

type DeleteBucketReplicationResp struct{}

type CreateAWSBucketReq struct {
	AWSBucketReq

	ProjectID uint64
	Region    string
}

type AWSBucketReq struct {
	Name         string
	AWSAccountID string
	Region       string
}

func (req *AWSBucketReq) ToGetAWSClientReq() *dfs3.GetAWSClientReq {
	return &dfs3.GetAWSClientReq{
		AccountID: req.AWSAccountID,
		Region:    req.Region,
	}
}

type PutAWSBucketTagsReq struct {
	AWSBucketReq

	Tags map[string]string
}

type EnableAWSBucketEncryptionReq struct {
	AWSBucketReq

	AwsKmsArn *string
}

type EnableAWSBucketVersioningReq struct {
	AWSBucketReq
}

const (
	DataflowServiceInfraRoleFormat = "arn:aws:iam::%s:role/dataflow-service-infra-role"
)

type AddAWSAllowRoleArnToBucketPolicyReq struct {
	AWSBucketReq

	IAMRoleARNs []string
}

type AddAWSAllowRoleArnToBucketPolicyResp struct {
	IAMRoleARNs []string
}

type DeleteAWSRoleArnFromBucketPolicyReq struct {
	AWSBucketReq

	IAMRoleARNs []string
}

type DeleteAWSRoleArnFromBucketPolicyResp struct {
	IAMRoleARNs []string
}

func BuildDataflowServiceInfraRoleARN(awsAccountID string) string {
	return fmt.Sprintf(DataflowServiceInfraRoleFormat, awsAccountID)
}

type AddBucketLifecycleConfigurationReq struct {
	AWSBucketReq

	LifecycleRule *AWSLifecycleRule
}

type AWSLifecycleRule struct {
	ID *string

	NoncurrentVersionExpiration *AWSNoncurrentVersionExpiration
}

type AWSNoncurrentVersionExpiration struct {
	NewerNoncurrentVersions *int64 `type:"integer"`
	NoncurrentDays          *int64 `type:"integer"`
}

type AddAWSBucketReplicationReq struct {
	AWSBucketReq

	ReplicationRule *AWSReplicationRule
}

type AWSReplicationRule struct {
	ID *string `type:"string"`

	Destination *AWSDestination           `type:"structure" required:"true"`
	Filter      *AWSReplicationRuleFilter `type:"structure"`
}

type AWSDestination struct {
	Bucket *string `type:"string" required:"true"`
}

type AWSReplicationRuleFilter struct {
	Prefix *string `type:"string"`
}

type AddAWSBucketReplicationResp struct {
	RuleIDs []string
}

type DeleteAWSBucketReplicationReq struct {
	AWSBucketReq
	RuleID *string
}

type DeleteAWSBucketReplicationResp struct {
	RuleIDs []string
}

type ModifyReplicationRTCReq struct {
	AWSBucketReq
	RuleID    string
	EnableRTC bool
}

// ---- Azure start ---- //
type AzureEncryptionParams struct {
	entity.AzureCmekParams
}

type AzureBucketReq struct {
	Name           string
	SubscriptionID string
}

type CheckAzureBucketReq struct {
	Name           string
	SubscriptionID string
}

type CreateAzureBucketReq struct {
	Name           string
	SubscriptionID string
	Region         string
	Tags           map[string]string
	ProjectID      string
}

type CreateAzureBucketContainerReq struct {
	SubscriptionID string
	Name           string
}

type EnableAzureBucketEncryptionReq struct {
	AzureBucketReq
	AzureEncryptionParams
}

type GenerateAzureSASTokenReq struct {
	Name           string
	SubscriptionID string
	Expiration     time.Duration
}

type DeleteAzureBucketReq struct {
	Name           string
	SubscriptionID string
}

// ---- Azure end ---- //

type CheckGCPBucketReq struct {
	Name string
}

type CreateGCPBucketReq struct {
	Name      string
	ProjectID string
	Regions   []string
	Tags      map[string]string
}

type DeleteGCPBucketReq struct {
	Name string
}

type GCPAddAllowPolicyToBucketReq struct {
	BucketName         string
	IAMServiceAccounts []string
}

type GCPAddAllowPolicyToBucketResp struct {
	IAMServiceAccounts []string
}

type GCPDeleteAllowPolicyFromBucketReq struct {
	BucketName         string
	IAMServiceAccounts []string
}

type GCPDeleteAllowPolicyFromBucketResp struct {
	IAMServiceAccounts []string
}

type GCPPutBucketTags struct {
	Name string
	Tags map[string]string
}
