package cluster

import (
	"context"

	"github.com/pingcap/dbaas/central/db"
	"github.com/pingcap/dbaas/central/db/entity"
	"github.com/pingcap/dbaas/central/db/tenant"
	"github.com/pingcap/dbaas/central/grpc/grpcli"
	"github.com/pingcap/errcode"
	"github.com/pingcap/errors"
	"github.com/tidbcloud/idl/pbgen/proto/core"
	"github.com/tidbcloud/pkgv2/bizerr"
	"github.com/tidbcloud/pkgv2/log"
	"gorm.io/gorm"
)

type CreateNetworkPeerParams4Aws struct {
	PeerAccountId string
}

type CreateNetworkPeerParams4Gcp struct {
	PeerProjectId string
}

type CreateNetworkPeerParams struct {
	ProjectId     uint64
	CloudProvider string
	Region        string
	PeerRegion    string
	PeerVpcCidr   string
	PeerNetwork   string
	Type          core.NetworkPeer_Type

	Aws CreateNetworkPeerParams4Aws
	Gcp CreateNetworkPeerParams4Gcp
}

func validateCreateReqByOrgPlan(ctx context.Context, user *tenant.User) error {
	var t entity.Tenant
	err := db.Transaction(func(tx *gorm.DB) error {
		return entity.NewTenantQuerySet(tx.Preload("Quotas")).IDEq(user.TenantID).One(&t)
	})
	if err != nil {
		return err
	}

	plan := t.Plan
	if plan == entity.TenantPlanNewUser || plan == entity.TenantPlanFreeTrial {
		return errcode.NewInvalidInputErr(errors.New("free trial users are not allowed to create vpc peering"))
	}
	return nil
}

func (c UserContext) CreateNetworkPeer(ctx context.Context, params *CreateNetworkPeerParams) (uint64, error) {
	return CreateNetworkPeerImp(ctx, params, c.tenantAndUser)
}

func CreateNetworkPeerImp(ctx context.Context, params *CreateNetworkPeerParams, creator *tenant.User) (uint64, bizerr.BizError) {
	logger := log.WithContextS(ctx)

	if err := validateCreateReqByOrgPlan(ctx, creator); err != nil {
		logger.Infof("validateCreateReqByOrgPlan failed: %v", err)
		return 0, bizerr.New(bizerr.ErrCodeParams, err.Error())
	}

	peering := &core.NetworkPeer{
		Id:            0,
		TenantId:      0,
		ProjectId:     params.ProjectId,
		CloudProvider: params.CloudProvider,
		Region:        params.Region,
		PeerRegion:    params.PeerRegion,
		PeerVpcCidr:   params.PeerVpcCidr,
		PeerNetwork:   params.PeerNetwork,
		Type:          params.Type,
		Status:        core.NetworkPeer_STATUS_UNSPECIFIED,
		Aws: &core.NetworkPeerInfo4Aws{
			PeerAccountId:   params.Aws.PeerAccountId,
			VpcPeeringId:    "",
			PrivateHostZone: "",
		},
		Gcp: &core.NetworkPeerInfo4Gcp{
			PeerProjectId: params.Gcp.PeerProjectId,
		},
	}
	return grpcli.CreateNetworkPeer(ctx, peering, creator.ID.Uint64())
}
