package account

import (
	"fmt"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/infra-provider/pkg/consts"
)

type NetworkInfo struct {
	// ServiceRoleName is the name of the service role in EKS cluster creation.
	ServiceRoleName string `json:"serviceRoleName"`

	// AssumeRoleName is the name of IAM role that cluster-controller assumes it to make AWS API calls in dataplane accounts.
	AssumeRoleName         string `json:"assumeRoleName"`
	AssumeRoleExternalID   string `json:"assumeRoleExternalID"`
	ReadonlyAssumeRoleName string `json:"readonlyAssumeRoleName"`

	// AWSClusterServerRoleARN is the AWS IAM role ARN used by the cluster-server running on AWS
	AWSClusterServerRoleARN string `json:"awsClusterServerRoleARN"`
	// GCPClusterServerSAName is the GCP IAM SA name used by the cluster-server running on GCP
	GCPClusterServerSAName string `json:"gcpClusterServerSAName"`
}

type ClusterInfo struct {
	ComponentPCAARN string `json:"componentPCAARN"`
}

// LegacyInfoGetter return the info about account to use.
type LegacyInfoGetter interface {
	Network(n *cloudv1.Network) (*NetworkInfo, error)
	Cluster(n *cloudv1.Network, c *cloudv1.Cluster) (*ClusterInfo, error)
}

type Getter interface {
	GetComponentPCAARN() string
	GetServiceRoleName() string
	GetAssumeRoleName() string
	GetAssumeRoleExternalID() string
}

// Info implements Selector.
// use to just read from config file and use one account.
type Info struct {
	NetworkInfo `json:",inline"`
	ClusterInfo `json:",inline"`
}

var _ LegacyInfoGetter = &Info{}
var _ Getter = &Info{}

func (info *NetworkInfo) Valid(provider string) error {
	if provider == consts.ProviderTypeEKS {
		if info.ServiceRoleName == "" {
			return fmt.Errorf("ServiceRoleName is empty")
		}

		if info.AssumeRoleName == "" {
			return fmt.Errorf("AssumeRoleName is empty")
		}

		if info.ReadonlyAssumeRoleName == "" {
			return fmt.Errorf("ReadonlyAssumeRoleName is empty")
		}

		if info.AWSClusterServerRoleARN == "" {
			return fmt.Errorf("AWSClusterServerRoleARN is empty")
		}
	} else if provider == consts.ProviderTypeGKE {
		if info.GCPClusterServerSAName == "" {
			return fmt.Errorf("GCPClusterServerSAName is empty")
		}
	}

	return nil
}

func (info *ClusterInfo) Valid(provider string) error {
	if info.ComponentPCAARN == "" {
		return fmt.Errorf("ComponentPCAARN is empty")
	}

	return nil
}

func (info *Info) Valid(provider string) error {
	err := info.NetworkInfo.Valid(provider)
	if err != nil {
		return err
	}

	err = info.ClusterInfo.Valid(provider)
	if err != nil {
		return err
	}

	return nil
}

// Network implements Selector interface.
func (info *Info) Network(_ *cloudv1.Network) (*NetworkInfo, error) {
	ret := info.NetworkInfo
	return &ret, nil
}

// Cluster implements Selector interface.
func (info *Info) Cluster(_ *cloudv1.Network, _ *cloudv1.Cluster) (*ClusterInfo, error) {
	ret := info.ClusterInfo
	return &ret, nil
}

func (info *Info) GetServiceRoleName() string {
	return info.ServiceRoleName
}

func (info *Info) GetAssumeRoleName() string {
	return info.AssumeRoleName
}
func (info *Info) GetAssumeRoleExternalID() string {
	return info.AssumeRoleExternalID
}

func (info *Info) GetComponentPCAARN() string {
	return info.ComponentPCAARN
}
