package cluster

import (
	"context"
	"fmt"

	"github.com/pingcap/dbaas/central/db"
	"github.com/pingcap/dbaas/central/db/dbutil"
	"github.com/pingcap/dbaas/central/db/entity"
	infraapi "github.com/pingcap/dbaas/central/infra-api"
	"github.com/pingcap/errors"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"gorm.io/gorm"
)

type DataIngestionProfile struct {
	Type          string
	AwsExternalId string
	AwsAccountId  string
	GcpAccountId  string
}

func (c UserContext) GetDataIngestionProfile(ctx context.Context, clusterID entity.ID) (*DataIngestionProfile, error) {
	var (
		cluster  entity.Cluster
		region   *entity.Region
		provider *entity.Provider
		err      error
	)
	err = db.Transaction(func(tx *gorm.DB) error {
		cluster, err = dbutil.GetCluster(tx, clusterID)
		if err != nil {
			return err
		}
		provider, region, err = dbutil.GetClusterProviderAndRegion(ctx, tx, cluster)
		return err
	})
	if err != nil {
		return nil, err
	}

	isXAccount := cluster.CrossAccountDeploymentID != 0
	providerType, err := infraapi.GetClusterProviderType(cluster.Provider.Name, cluster.Free, isXAccount)
	if err != nil {
		return nil, errors.Annotate(err, "failed to get provider type")
	}
	network, err := c.api.GetNetwork(context.Background(), providerType, cluster.ProjectID.Uint64(), region.Name)
	if err != nil {
		return nil, errors.Annotate(err, "failed to query network")
	}

	awsAccountId := ""
	if provider.Name == entity.Aws {
		awsAccountId = network.Status.IAM.AccountID

		// Drop this branch when aws provider set network.Status.IAM.AccountID
		// and all network reconciled.
		if providerType == infraapi.ProviderTypeAWS {
			gs, err := cloudv1.GardenerNetworkStatusFromNetwork(network)
			if err != nil {
				return nil, errors.AddStack(err)
			}
			if gs.AWS.AccountID != nil {
				awsAccountId = *gs.AWS.AccountID
			}
		}
	}

	// for compatible with old version. we use projectId as externalId for cluster in new version.
	externalId := fmt.Sprint(cluster.ProjectID.Uint64())
	if network.Status.IAM.ExternalId != "" {
		externalId = network.Status.IAM.ExternalId
	}

	return &DataIngestionProfile{
		Type:          provider.Name.String(),
		AwsExternalId: externalId,
		AwsAccountId:  awsAccountId,
		GcpAccountId:  network.Status.IAM.ServiceAccountEmail,
	}, nil
}
