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 (
	ActionDeployNewNextGenRegion opent.ActionMetadata = opent.ActionMetadata{
		Name: "DeployNewNextGenRegion",
		Type: opent.ActionTypeAuto,
	}
)

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

func NewDeployNewNextGenRegion(comps *actions.Components) actions.AutoAction {
	return &deployNewNextGenRegion{comps: comps}
}

func (a *deployNewNextGenRegion) Metadata() opent.ActionMetadata {
	return ActionDeployNewNextGenRegion
}

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

func (a *deployNewNextGenRegion) 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.DeployNewNextGenRegion(req)
	if err != nil {
		return actions.FailedActionResult(err), nil
	}

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

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

func (a *deployNewNextGenRegion) getParam(instance *opent.Instance) (*fadcli.DeployNextGenRegionReq, error) {
	paramMap := make(map[opent.ParamName]string)
	paramList := []opent.ParamName{
		opent.ParamTiDBCloudInstance,
		opent.ParamProvider,
		opent.ParamRegionName,
		opent.ParamLogicalRegionName,
		opent.ParamO11YRegionName,
		opent.ParamMAccount,
		opent.ParamDAccounts,
		opent.ParamO11YAccount,
		opent.ParamRdsName,
		opent.ParamCreateRds,
		opent.ParamAvailabilityZones,
	}
	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.DeployNextGenRegionReq{
		TiDBCloudInstance: paramMap[opent.ParamTiDBCloudInstance],
		Provider:          paramMap[opent.ParamProvider],
		RegionName:        paramMap[opent.ParamRegionName],
		LogicalRegionName: paramMap[opent.ParamLogicalRegionName],
		O11YRegionName:    paramMap[opent.ParamO11YRegionName],
		Trigger:           instance.Applicant,
		MAccount:          paramMap[opent.ParamMAccount],
		DAccounts:         paramMap[opent.ParamDAccounts],
		O11YAccount:       paramMap[opent.ParamO11YAccount],
		TraceID:           traceID,
		RdsName:           paramMap[opent.ParamRdsName],
		CreateRds:         paramMap[opent.ParamCreateRds],
		AvailabilityZones: paramMap[opent.ParamAvailabilityZones],
	}, nil
}
