package action

import (
	"fmt"
	"strconv"

	"braces.dev/errtrace"
	"github.com/tidbcloud/fastflow/pkg/entity/run"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"

	globaldedicatedv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/dedicated/v1"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/adapter/dedicatedglobal"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/constant"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/repository"
	"github.com/tidbcloud/tidb-management-service/utilities/workflow"
)

type ShutdownUpgradeClusterAction struct {
	migrationClusterRepo repository.MigrationClusterRepo
	dedicatedCli         dedicatedglobal.DedicatedGlobal
}

func NewShutdownUpgradeClusterAction(
	migrationClusterRepo repository.MigrationClusterRepo,
	dedicatedCli dedicatedglobal.DedicatedGlobal,
) *ShutdownUpgradeClusterAction {
	return &ShutdownUpgradeClusterAction{
		migrationClusterRepo: migrationClusterRepo,
		dedicatedCli:         dedicatedCli,
	}
}

func (c *ShutdownUpgradeClusterAction) Name() string {
	return constant.TaskDedicatedShutdownUpgradeCluster
}

func (c *ShutdownUpgradeClusterAction) Run(ctx run.ExecuteContext, params any) error {
	cctx, span := workflow.GenerateContext(ctx)
	defer span.End()

	tilog.Info(cctx, "shutdown upgrade cluster action start")

	migrationClusterIdStr, ok := ctx.GetVar(constant.KeyMigrationClusterID)
	if !ok {
		return fmt.Errorf("migration cluster id not found")
	}
	migrationClusterID, err := strconv.ParseUint(migrationClusterIdStr, 10, 64)
	if err != nil {
		return fmt.Errorf("parse migration cluster id %w", err)
	}
	migrationCluster, err := c.migrationClusterRepo.Load(cctx, migrationClusterID)
	if err != nil {
		return errtrace.Wrap(err)
	}

	targetClusterId := migrationCluster.GetTargetClusterId()

	_, err = c.dedicatedCli.ShutdownUpgradeCluster(
		cctx,
		&globaldedicatedv1.ShutdownUpgradeClusterRequest{
			ClusterId:       targetClusterId,
			TargetVersion:   migrationCluster.TargetClusterVersion,
			ValidateOnly:    true,
			TidbImageTag:    migrationCluster.GetTidbImageTag(),
			TikvImageTag:    migrationCluster.GetTikvImageTag(),
			PdImageTag:      migrationCluster.GetPdImageTag(),
			TiflashImageTag: migrationCluster.GetTiflashImageTag(),
		},
	)
	if err != nil {
		tilog.Error(cctx, "shutdown upgrade cluster request validation failed", zap.Error(err))
		return errtrace.Wrap(err)
	}

	tilog.Info(cctx, "shutdown upgrade cluster request validation passed, starting shutdown upgrade")
	_, err = c.dedicatedCli.ShutdownUpgradeCluster(
		cctx,
		&globaldedicatedv1.ShutdownUpgradeClusterRequest{
			ClusterId:       targetClusterId,
			TargetVersion:   migrationCluster.TargetClusterVersion,
			ValidateOnly:    false,
			TidbImageTag:    migrationCluster.GetTidbImageTag(),
			TikvImageTag:    migrationCluster.GetTikvImageTag(),
			PdImageTag:      migrationCluster.GetPdImageTag(),
			TiflashImageTag: migrationCluster.GetTiflashImageTag(),
		},
	)
	if err != nil {
		tilog.Error(cctx, "shutdown upgrade cluster request failed", zap.Error(err))
		return errtrace.Wrap(err)
	}

	tilog.Info(cctx, "shutdown upgrade cluster request passed, shutdown upgrade cluster action end")
	return nil
}
