package ngoperation

import (
	"context"
	"fmt"

	ccproto "github.com/tidbcloud/config-center/proto/config_center"
	opent "github.com/tidbcloud/devops/entity/operation"
	"github.com/tidbcloud/devops/pkg/service/operation/actions"
)

var (
	ActionModifyNgImage opent.ActionMetadata = opent.ActionMetadata{
		Name: "ModifyNgGlobalImage",
		Type: opent.ActionTypeAuto,
	}
)

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

func NewModifyNgComponentImage(comps *actions.Components) actions.AutoAction {
	return &modifyNgImage{
		comps: comps,
	}
}

func (p *modifyNgImage) Metadata() opent.ActionMetadata {
	return ActionModifyNgImage
}

func (p *modifyNgImage) PreCheck(ctx context.Context, instance *opent.Instance) error {
	_, err := p.getParam(instance)
	if err != nil {
		return err
	}

	return nil
}

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

	_, err = p.comps.CfgCenterCli.ConfigAPI.UpdateComponentImage(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("failed to update component image: %w", err)
	}

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

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

func (p *modifyNgImage) getParam(instance *opent.Instance) (*ccproto.UpdateComponentImageRequest, error) {
	clusterTypeStr, ok := instance.GetParam(opent.ParamCloudConfigClusterType)
	if !ok {
		return nil, fmt.Errorf("param %s is required", opent.ParamCloudConfigClusterType)
	}
	clusterTypeVal, ok := ccproto.ClusterType_value[clusterTypeStr]
	if !ok {
		return nil, fmt.Errorf("invalid cluster type: %s", clusterTypeStr)
	}
	clusterType := ccproto.ClusterType(clusterTypeVal)

	component, ok := instance.GetParam(opent.ParamNgModifyImageComponent)
	if !ok {
		return nil, fmt.Errorf("param %s is required", opent.ParamNgModifyImageComponent)
	}
	version, ok := instance.GetParam(opent.ParamCloudConfigVersion)
	if !ok {
		return nil, fmt.Errorf("param %s is required", opent.ParamCloudConfigVersion)
	}
	baseImage, ok := instance.GetParam(opent.ParamNgModifyImageBaseImage)
	if !ok {
		return nil, fmt.Errorf("param %s is required", opent.ParamNgModifyImageBaseImage)
	}
	tag, ok := instance.GetParam(opent.ParamNgModifyImageTag)
	if !ok {
		return nil, fmt.Errorf("param %s is required", opent.ParamNgModifyImageTag)
	}

	return &ccproto.UpdateComponentImageRequest{
		ClusterType:      clusterType,
		ComponentName:    component,
		ComponentVersion: version,
		BaseImage:        baseImage,
		Tag:              tag,
	}, nil

}
