package opsaction

import (
	"context"
	"fmt"

	ccent "github.com/tidbcloud/devops/entity/cloudconfig"
	opent "github.com/tidbcloud/devops/entity/operation"
	ccapi "github.com/tidbcloud/devops/pkg/service/cloudconfig/api"
	"github.com/tidbcloud/devops/pkg/service/operation/actions"
)

var (
	ActionUpdateDefaultVersion opent.ActionMetadata = opent.ActionMetadata{
		Name: "UpdateDefaultVersion",
		Type: opent.ActionTypeAuto,
	}
)

type updateDefaultVersionParam struct {
	ClusterType ccent.ClusterType
	Version     string
}

type updateDefaultVersion struct {
	actions.BaseAction

	comps *actions.Components
}

func NewUpdateDefaultVersion(comps *actions.Components) actions.AutoAction {
	return &updateDefaultVersion{comps: comps}
}

func (a *updateDefaultVersion) Metadata() opent.ActionMetadata {
	return ActionUpdateDefaultVersion
}

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

	versions, err := a.comps.CloudConfigAPI.ListAvailableClusterVersions(ctx, param.ClusterType)
	if err != nil {
		return err
	}

	for _, v := range versions {
		if v.Version == param.Version {
			if v.IsDefault {
				return fmt.Errorf("version %s is already default version", param.Version)
			}

			return nil
		}
	}

	return fmt.Errorf("version %s is not found", param.Version)
}

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

	err = a.comps.CloudConfigAPI.UpdateDefaultClusterVersion(ctx, param.ClusterType, param.Version, ccapi.UpdateDefaultVersionParam{
		ForGlobal: true,
	})
	if err != nil {
		return actions.FailedActionResult(err), nil
	}
	return actions.SucceededActionResult(nil), nil
}

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

func (a *updateDefaultVersion) getParam(instance *opent.Instance) (*updateDefaultVersionParam, error) {
	p := &updateDefaultVersionParam{}

	clusterType, exist := instance.GetParam(opent.ParamCloudConfigClusterType)
	if !exist {
		return nil, fmt.Errorf("param %s not found", opent.ParamCloudConfigClusterType)
	}
	p.ClusterType = ccent.ClusterType(clusterType)

	version, exist := instance.GetParam(opent.ParamCloudConfigVersion)
	if !exist {
		return nil, fmt.Errorf("param %s not found", opent.ParamCloudConfigVersion)
	}
	p.Version = version

	return p, nil
}
