package migrate

import (
	"context"

	"github.com/tidbcloud/core-svc/core_ctx/infra/feature_gate"
	"github.com/tidbcloud/core-svc/idl/pbgen/proto/core"
	"github.com/tidbcloud/core-svc/model"
	"github.com/tidbcloud/pkgv2/log"
	"gorm.io/gorm"
)

// add OnNewArch field
var _ = AddCoreMigrateRecord(
	"202211301140",
	func(db *gorm.DB) error {
		if err := db.AutoMigrate(&model.Cluster{}); err != nil {
			return err
		}

		logger := log.WithContextS(context.Background())
		return db.Transaction(func(tx *gorm.DB) error {
			logger.Infof("start migrate on_new_arch")

			statuses := []core.ClusterStatus{
				core.ClusterStatus_CLUSTER_STATUS_INITIALIZING,
				core.ClusterStatus_CLUSTER_STATUS_PREPARING,
				core.ClusterStatus_CLUSTER_STATUS_LAUNCHING,
				core.ClusterStatus_CLUSTER_STATUS_SCALING,
				core.ClusterStatus_CLUSTER_STATUS_RECOVERING,
				core.ClusterStatus_CLUSTER_STATUS_NORMAL,
				core.ClusterStatus_CLUSTER_STATUS_PAUSING,
				core.ClusterStatus_CLUSTER_STATUS_PAUSED,
				core.ClusterStatus_CLUSTER_STATUS_RESUMING,
				core.ClusterStatus_CLUSTER_STATUS_DELETED,
				core.ClusterStatus_CLUSTER_STATUS_DELETECOMPLETE,
			}
			// load
			var clusters []*model.Cluster
			if err := db.Model(&model.Cluster{}).
				Preload("Provider").Preload("ComponentsV2.Region").
				Where("status in (?)", statuses).Where("free = ?", false).
				Find(&clusters).Error; err != nil {
				return err
			}

			// migrate
			for _, cluster := range clusters {
				region := ""
				for _, each := range cluster.ComponentsV2 {
					if each.Region != nil {
						region = each.Region.Name
						break
					}
				}
				cluster.OnNewArch = feature_gate.OnNewArch(cluster.TenantID.Uint64(), cluster.ProjectID.Uint64(), string(cluster.Provider.Name), region)
				if cluster.OnNewArch { // only need to update from `false` to `true`
					logger.Infof("cluster %d is on new arch", cluster.ID)
					if err := cluster.Update(tx, model.ClusterDBSchema.OnNewArch); err != nil {
						return err
					}
				}
			}

			logger.Infof("finish migrate on_new_arch")
			return nil
		})
	},
)
