package infra

import (
	"context"
	"fmt"

	"github.com/tidbcloud/core-svc/idl/pbgen/proto/core"

	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
)

type ResourceResult struct {
	ClusterNum     uint64
	BackupNUm      uint64
	VPCPeeringNum  uint64
	IsHaveResource bool
	ResourcesMsg   string
}

func checkResource(ctx context.Context, id uint64, idType string, projectIds []uint64, countFunc func(context.Context, []uint64) (int64, error)) (*ResourceResult, error) {
	resourceResult := &ResourceResult{}
	clusterCount, err := countFunc(ctx, []uint64{id})
	tilog.Info(ctx, "query clusters under the "+idType, zap.Uint64(idType, id), zap.Any("clusters_count", clusterCount))
	if err != nil {
		tilog.Error(ctx, "CountClustersBy"+idType+" fail", zap.Uint64(idType, id), zap.Error(err))
		return nil, err
	}
	networkPeerCount, err := countNetworkPeer(ctx, projectIds)
	if err != nil {
		tilog.Error(ctx, "countNetworkPeer "+idType+" fail", zap.Uint64(idType, id), zap.Error(err))
		return nil, err
	}

	msg := ""
	if clusterCount > 0 {
		resourceResult.ClusterNum = uint64(clusterCount)
		resourceResult.IsHaveResource = true
		msg += fmt.Sprintf(" Cluster: %d", clusterCount)
	}
	if networkPeerCount > 0 {
		resourceResult.VPCPeeringNum = uint64(networkPeerCount)
		resourceResult.IsHaveResource = true
		msg += fmt.Sprintf("   VPC Peering : %d", networkPeerCount)
	}

	if resourceResult.IsHaveResource {
		str := "There are resources in the " + idType + " that have not been deleted:<br>【" + msg + "】"
		resourceResult.ResourcesMsg = str
	}
	tilog.Info(ctx, "Check"+idType+"Resource", zap.Uint64(idType, id), zap.Any("resourceResult", resourceResult))
	return resourceResult, nil
}

func CheckOrgResource(ctx context.Context, orgId uint64, projectIds []uint64) (*ResourceResult, error) {

	return checkResource(ctx, orgId, "org", projectIds, GetHandler().CountClustersByOrg)
}
func countNetworkPeer(ctx context.Context, projectIds []uint64) (int64, error) {
	if len(projectIds) == 0 {
		return 0, nil
	}

	filter := &core.NetworkPeerFilter{
		CloudProvider: "aws",
		Statuses:      []core.NetworkPeer_Status{core.NetworkPeer_STATUS_ACTIVE, core.NetworkPeer_STATUS_PENDING},
		Types: []core.NetworkPeer_Type{
			core.NetworkPeer_TYPE_CUSTOMER_READONLY,
			core.NetworkPeer_TYPE_CUSTOMER,
		},
		ProjectIds: projectIds,
	}
	awsConut, err := GetHandler().CountNetworkPeers(ctx, filter)
	if err != nil {
		tilog.Error(ctx, "CountNetworkPeers fail", zap.Error(err))
		return 0, err
	}
	filter.CloudProvider = "gcp"
	gcpConut, err := GetHandler().CountNetworkPeers(ctx, filter)
	if err != nil {
		tilog.Error(ctx, "CountNetworkPeers fail", zap.Error(err))
		return 0, err
	}
	return awsConut + gcpConut, nil
}

func CheckProjectResource(ctx context.Context, projectId uint64) (*ResourceResult, error) {

	return checkResource(ctx, projectId, "project", []uint64{projectId}, GetHandler().CountClustersByProject)
}
