package deploy

import (
	"context"
	"fmt"

	"github.com/go-gormigrate/gormigrate/v2"
	"github.com/gogo/protobuf/proto"
	"github.com/tidbcloud/cluster-service-ng/domain/workflow"
	"github.com/tidbcloud/cluster-service-ng/domain/workflow/action"
	"github.com/tidbcloud/cluster-service-ng/pkg/clusterconfig"
	"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"
	configcenter "github.com/tidbcloud/config-center/proto/config_center"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

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

// apply tidb sem config auto update for shared pools
func (m *migrator) migrate20251204(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
				}

				CreateTiDBSemConfigAction := action.NewCreateTiDBSemConfigAction(
					m.sharedPoolRepo,
					m.dataplaneManager,
					m.clusterConfig,
				)

				tilog.Info(ctx, "start to do auto update tidb sem config for shared pools")

				for _, sharedPool := range sharedPools {
					tilog.Info(ctx, "do auto update tidb sem config for shared pool", zap.String("sharedPoolId", sharedPool.GetId()))

					// auto create or update tidb sem config
					_, err := m.clusterConfig.GetClient().AutoUpdateClusterConfigurationFile(ctx, &configcenter.AutoUpdateClusterConfigurationFileRequest{
						ClusterType:           configcenter.ClusterType_SHARED_POOL,
						ClusterId:             sharedPool.GetId(),
						ConfigurationFilename: clusterconfig.TiDBSemConfig,
						ConfigurationType:     proto.String(clusterconfig.TiDBSemConfig),
						Format:                configcenter.Format_JSON.Enum(),
						Version:               sharedPool.GetVersion(),
					})
					if err != nil {
						return fmt.Errorf("failed to get or create tidb sem config for shared pool %s: %w", sharedPool.GetId(), err)
					}

					tilog.Info(ctx, "create tidb sem config from config center completed", zap.String("sharedPoolId", sharedPool.GetId()))

					err = CreateTiDBSemConfigAction.Invoke(actions.ActionArgs{
						workflow.SharedPoolIdKey: actions.ActionArgString(sharedPool.GetId()),
						utils.TraceIdKey:         utils.GetTraceId(ctx),
					})
					if err != nil {
						return fmt.Errorf("failed to apply tidb sem config for shared pool %s: %w", sharedPool.GetId(), err)
					}
					tilog.Info(ctx, "apply tidb sem config completed", zap.String("sharedPoolId", sharedPool.GetId()))
				}
				return nil
			})
		})
	}
}
