package regionaction

import (
	"context"
	"crypto/md5"
	"fmt"
	"strconv"

	"github.com/google/uuid"
	opent "github.com/tidbcloud/devops/entity/operation"
	"github.com/tidbcloud/devops/pkg/infra/clients/fadcli"
	"github.com/tidbcloud/devops/pkg/service/operation/actions"
)

var (
	ActionDeployNewRegion opent.ActionMetadata = opent.ActionMetadata{
		Name: "DeployNewRegion",
		Type: opent.ActionTypeAuto,
	}
)

type deployNewRegion struct {
	actions.BaseAction
	comps *actions.Components
}

func NewDeployNewRegion(comps *actions.Components) actions.AutoAction {
	return &deployNewRegion{comps: comps}
}

func (a *deployNewRegion) Metadata() opent.ActionMetadata {
	return ActionDeployNewRegion
}

func (a *deployNewRegion) PreCheck(ctx context.Context, instance *opent.Instance) error {
	return nil
}

func (a *deployNewRegion) Start(ctx context.Context, instance *opent.Instance) (*actions.ActionResult, error) {
	req, err := a.getParam(instance)
	if err != nil {
		return actions.FailedActionResult(err), nil
	}

	err = a.comps.FadCli.DeployNewRegion(req)
	if err != nil {
		return actions.FailedActionResult(err), nil
	}

	return actions.SucceededActionResult(nil), nil // return succeeded directly
}

func (a *deployNewRegion) Result(ctx context.Context, instance *opent.Instance) (*actions.ActionResult, error) {
	return actions.SucceededActionResult(nil), nil
}

func (a *deployNewRegion) getParam(instance *opent.Instance) (*fadcli.DeployRegionReq, error) {
	paramMap := make(map[opent.ParamName]string)
	paramList := []opent.ParamName{
		opent.ParamTiDBCloudInstance,
		opent.ParamProvider,
		opent.ParamRegionName,
		opent.ParamLogicalRegionName,
		opent.ParamO11YRegionName,
		opent.ParamSPUsCollectionName,
		opent.ParamSKUCollectionName,
		opent.ParamMAccount,
		opent.ParamDAccounts,
		opent.ParamO11YAccount,
	}
	for _, param := range paramList {
		paramMap[param], _ = instance.GetParam(param)
		// dont need to check missing param here, because it will be checked in action validation
	}

	traceID := uuid.New().String()
	if instance.ApprovalID != nil {
		traceID = fmt.Sprintf("%x", md5.Sum([]byte(strconv.Itoa(int(*instance.ApprovalID)))))
	}

	return &fadcli.DeployRegionReq{
		TiDBCloudInstance:  paramMap[opent.ParamTiDBCloudInstance],
		Provider:           paramMap[opent.ParamProvider],
		RegionName:         paramMap[opent.ParamRegionName],
		LogicalRegionName:  paramMap[opent.ParamLogicalRegionName],
		O11YRegionName:     paramMap[opent.ParamO11YRegionName],
		Trigger:            instance.Applicant,
		SPUsCollectionName: paramMap[opent.ParamSPUsCollectionName],
		SKUCollectionName:  paramMap[opent.ParamSKUCollectionName],
		MAccount:           paramMap[opent.ParamMAccount],
		DAccounts:          paramMap[opent.ParamDAccounts],
		O11YAccount:        paramMap[opent.ParamO11YAccount],
		TraceID:            traceID,
	}, nil
}
