package deploy

import (
	"context"
	"fmt"

	"github.com/go-gormigrate/gormigrate/v2"
	apiv1 "github.com/tidbcloud/cluster-service-ng/api/cluster-service-ng/v1beta"
	"github.com/tidbcloud/cluster-service-ng/domain/workflow"
	"github.com/tidbcloud/cluster-service-ng/domain/workflow/action"
	"github.com/tidbcloud/cluster-service-ng/pkg/runtime/actions"
	"github.com/tidbcloud/cluster-service-ng/pkg/storage/repo"
	"github.com/tidbcloud/cluster-service-ng/pkg/utils"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

func init() {
	registerMigrateRecord((*migrator).updateClusterAgent_20260821080407)
}

// upgrade cluster agent and data cleaner
func (m *migrator) updateClusterAgent_20260821080407(ctx context.Context) gormigrate.MigrateFunc {
	return func(db *gorm.DB) error {
		return InvokeRunMigrateWithRetry(ctx, func() error {
			return db.Transaction(func(tx *gorm.DB) error {
				sharedPools, err := m.sharedPoolRepo.List(ctx, &repo.SharedPoolFilter{Deleted: false})
				if err != nil {
					return fmt.Errorf("failed to list shared pools: %w", err)
				}

				if len(sharedPools) == 0 {
					tilog.PlainInfo("no shared pools found, skip migration")
					return nil
				}

				applyClusterAgent := action.NewApplyClusterAgentAction(
					m.dataplaneManager,
					m.sharedPoolRepo,
					m.templateVersion,
					&m.csngConfig.ImageConfig,
					&m.csngConfig.BizConfig,
				)

				tilog.Info(ctx, "start to upgrade cluster agent and data cleaner for shared pools")

				for _, sharedPool := range sharedPools {
					tilog.Info(ctx, "upgrading cluster agent for shared pool", zap.String("sharedPoolId", sharedPool.GetId()))

					if sharedPool.GetPhase() == apiv1.SharedPool_CREATING {
						tilog.Info(ctx, "sharedPool is creating, skip cluster agent upgrade",
							zap.String("sharedPoolId", sharedPool.GetId()),
						)
						continue
					}

					err = applyClusterAgent.Invoke(actions.ActionArgs{
						workflow.SharedPoolIdKey: actions.ActionArgString(sharedPool.GetId()),
						utils.TraceIdKey:         utils.GetTraceId(ctx),
					})
					if err != nil {
						return fmt.Errorf("failed to apply cluster agent for shared pool %s: %w", sharedPool.GetId(), err)
					}

					tilog.Info(ctx, "upgrading cluster agent completed", zap.String("sharedPoolId", sharedPool.GetId()))
				}
				return nil
			})
		})
	}
}
