package versionupdater

import (
	"context"
	"time"

	"github.com/guregu/dynamo/v2"
	infra "github.com/tidbcloud/tidb-management-service/api/serverless_infra"
	infraclient "github.com/tidbcloud/tidb-management-service/api/serverless_infra/client"
	ctrl "sigs.k8s.io/controller-runtime"
)

var log = ctrl.Log.WithName("versionupdater")

type updater struct {
	infraClusterCli infraclient.Client
	elected         <-chan struct{}
	versionMap      map[string]string
}

func NewTiDBVersionUpdater(infraClusterCli infraclient.Client,
	versionMap map[string]string, elected <-chan struct{}) *updater {
	return &updater{
		infraClusterCli: infraClusterCli,
		elected:         elected,
		versionMap:      versionMap,
	}
}

func (u *updater) Start(ctx context.Context) {
	go func() {
		select {
		case <-ctx.Done():
			return
		case <-u.elected:
			rawClient := u.infraClusterCli.RawClient()
			dynamoTable, ok := rawClient.(dynamo.Table)
			if !ok {
				return
			}
			iter := dynamoTable.Scan().Iter()
			cluster := &infra.Cluster{}

			total := 0
			updated := 0
			for iter.Next(ctx, cluster) {
				total += 1
				tidbPool := cluster.Status.TidbPool
				version, ok := u.versionMap[tidbPool]
				log.Info("get cluster", "name", cluster.Name, "tidb pool", tidbPool,
					"current version", cluster.Status.TiDB.Version, "target version", version)
				if !ok {
					continue
				}
				if version != cluster.Status.TiDB.Version {
					cluster.Status.TiDB.Version = version
					err := u.infraClusterCli.Update(ctx, cluster)
					if err != nil {
						log.Error(err, "failed to update cluster", "cluster", cluster.Name)
						continue
					}
					log.Info("update tidb version", "cluster", cluster.Name)
					updated += 1
				}
				if total%10 == 0 {
					time.Sleep(time.Second)
				}
			}
			log.Info("update tidb version completed", "total", total, "updated", updated)
		}
	}()
}
