package vpc

import (
	"context"

	"github.com/tidbcloud/pkgv2/db"

	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/adapter/account"
	cidrrepo "github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/repository/cidr"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
)

type UpdateCidrParams struct {
	CidrID       uint64
	ProjectID    uint64
	CIDR         string
	ValidateOnly bool
}

type UpdateCidrSvc interface {
	Execute(ctx context.Context, params *UpdateCidrParams) (*ValidateOnlyResponse, bizerr.BizError)
}

type updateCidrSvc struct {
	cidrRepo    cidrrepo.Repo
	accountCli  account.Client
	helper      Helper
	transaction db.Transactioner
}

func NewUpdateCidrSvc(
	cidrRepo cidrrepo.Repo,
	accountCli account.Client,
	helper Helper,
	transaction db.Transactioner,
) UpdateCidrSvc {
	return &updateCidrSvc{
		cidrRepo:    cidrRepo,
		accountCli:  accountCli,
		helper:      helper,
		transaction: transaction,
	}
}

func (svc *updateCidrSvc) Execute(
	ctx context.Context,
	params *UpdateCidrParams,
) (*ValidateOnlyResponse, bizerr.BizError) {
	ctx, span := tracer.Start(ctx, "Domain.UpdateCidrSvc")
	defer span.End()

	var resp *ValidateOnlyResponse
	err := svc.transaction.Transaction(ctx, func(ctx context.Context) error {
		cidrEntity, err := svc.cidrRepo.Load(ctx, params.ProjectID, params.CidrID)
		if err != nil {
			return err
		}

		project, err := svc.accountCli.GetProject(ctx, cidrEntity.ProjectID)
		if err != nil {
			return err
		}

		err = svc.helper.CheckCidrState(ctx, cidrEntity, project)
		if err != nil {
			return err
		}

		cloudProviderName := cidrEntity.BasicRegion.CloudProviderName
		cidrMask, err := svc.helper.ValidateCIDR(params.CIDR, cloudProviderName, project.TenantID, project.ID)
		if err != nil {
			return err
		}

		if params.ValidateOnly {
			resp, err = svc.helper.BuildValidateOnlyResponse(
				ctx,
				cloudProviderName,
				params.CIDR,
				cidrMask,
				project,
				cidrEntity,
			)
			if err != nil {
				return err
			}
			return nil
		}

		cidrEntity.CIDR = params.CIDR
		err = svc.cidrRepo.Save(ctx, cidrEntity)
		if err != nil {
			return err
		}

		return nil
	})
	if err != nil {
		return nil, bizerr.WrapError(err, "update cidr failed")
	}

	return resp, nil
}
