package models

import (
	"fmt"

	"github.com/tidbcloud/infra-provider/regional-server/api/v1alpha1"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/common/constants"
)

type DataPlaneAccountInfo struct {
	*AWSAccountInfo
	*GCPAccountInfo
	*AzureAccountInfo
}

func (p DataPlaneAccountInfo) Is(key string) bool {
	if p.AWSAccountInfo != nil {
		return p.AWSAccountInfo.AWSAccount == key
	}
	if p.GCPAccountInfo != nil {
		return p.GCPAccountInfo.ProjectID == key
	}
	if p.AzureAccountInfo != nil {
		return p.AzureAccountInfo.SubscriptionID == key
	}
	return false
}

func (p DataPlaneAccountInfo) GetKey() string {
	if p.AWSAccountInfo != nil {
		return p.AWSAccountInfo.AWSAccount
	}
	if p.GCPAccountInfo != nil {
		return p.GCPAccountInfo.ProjectID
	}
	if p.AzureAccountInfo != nil {
		return p.AzureAccountInfo.SubscriptionID
	}
	return ""
}

func (p DataPlaneAccountInfo) GetAccountReference(providerConfigName string) *v1alpha1.AccountReference {
	accountRef := &v1alpha1.AccountReference{
		ProviderConfigName: providerConfigName,
	}
	if p.AWSAccountInfo != nil {
		accountRef.AccountID = p.AWSAccountInfo.AWSAccount
		accountRef.Role = p.AWSAccountInfo.AWSRole
	}
	if p.GCPAccountInfo != nil {
		accountRef.AccountID = p.GCPAccountInfo.ProjectID
	}
	if p.AzureAccountInfo != nil {
		accountRef.AccountID = p.AzureAccountInfo.SubscriptionID
	}

	return accountRef
}

func (p DataPlaneAccountInfo) GetAccountID() string {
	if p.AWSAccountInfo != nil {
		return p.AWSAccountInfo.AWSAccount
	}
	if p.GCPAccountInfo != nil {
		return p.GCPAccountInfo.ProjectID
	}
	if p.AzureAccountInfo != nil {
		return p.AzureAccountInfo.SubscriptionID
	}
	return ""
}

type AccountBindingTarget struct {
	TargetType constants.AccountBindingTargetType `yaml:"targetType"`
	TargetKey  string                             `yaml:"targetKey"`
}

func (a AccountBindingTarget) UniqueTargetName() string {
	return fmt.Sprintf("%s-%s", a.TargetType, a.TargetKey)
}

type AWSAccountInfo struct {
	AWSAccount  string `yaml:"awsAccount"`
	AWSRole     string `yaml:"awsRole"`
	CMEKEnabled bool   `yaml:"cmekEnabled"`
}

type GCPAccountInfo struct {
	ProjectID   string `yaml:"projectID"`
	CMEKEnabled bool   `yaml:"cmekEnabled"`
}

type AzureAccountInfo struct {
	SubscriptionID string `yaml:"subscriptionID"`
	CMEKEnabled    bool   `yaml:"cmekEnabled"`
}

type ListAccountOption interface {
	Apply(accounts []DataPlaneAccountInfo) []DataPlaneAccountInfo
}

type AccountFilter struct {
	CMEKEnabled bool
}

func (a AccountFilter) Apply(accounts []DataPlaneAccountInfo) []DataPlaneAccountInfo {
	results := make([]DataPlaneAccountInfo, 0)
	for _, account := range accounts {
		if account.AWSAccountInfo != nil && account.AWSAccountInfo.CMEKEnabled == a.CMEKEnabled {
			results = append(results, account)
		}
		if account.GCPAccountInfo != nil && account.GCPAccountInfo.CMEKEnabled == a.CMEKEnabled {
			results = append(results, account)
		}
		if account.AzureAccountInfo != nil && account.AzureAccountInfo.CMEKEnabled == a.CMEKEnabled {
			results = append(results, account)
		}
	}
	return results
}
