package metrics

import (
	"context"
	"sync"
	"time"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"

	"github.com/tidbcloud/tidb-management-service/serverless-global-service/domain/constant"
	"github.com/tidbcloud/tidb-management-service/serverless-global-service/domain/repository"
	"github.com/tidbcloud/tidb-management-service/serverless-global-service/domain/service/metrics"
)

var WatchClusterPendingTaskFailedTotal = prometheus.NewCounter(prometheus.CounterOpts{
	Namespace: constant.MetricsNamespace,
	Subsystem: "cluster",
	Name:      "pending_task_failed_total",
	Help:      "watch cluster pending task failed count",
})

type ClusterStatCollector struct {
	clusterRepo repository.ClusterRepo
	refreshOnce sync.Once
}

func NewClusterStatCollector(
	clusterRepo repository.ClusterRepo,
) *ClusterStatCollector {
	c := &ClusterStatCollector{
		clusterRepo: clusterRepo,
		refreshOnce: sync.Once{},
	}

	c.refreshOnce.Do(func() {
		go func() {
			for range time.Tick(time.Duration(15) * time.Second) {
				c.refresh()
			}
		}()
	})

	return c
}

func (c *ClusterStatCollector) refresh() {
	ctx := context.Background()
	clusters, err := c.clusterRepo.Query(ctx, &repository.ClusterQueryParameter{
		InCreatingStatus: true,
	})
	if err != nil {
		WatchClusterPendingTaskFailedTotal.Inc()
		tilog.Error(ctx, "query pending cluster failed", zap.Error(err))
		return
	}

	for _, c := range clusters {
		costTime := time.Since(c.CreatedAt).Seconds()

		if costTime > constant.LongPendingSec {
			metrics.ClusterInitializedLongTime.Inc()
			tilog.Warn(
				ctx,
				"the cluster initialize task cost long time",
				zap.String("cluster", c.ClusterId),
				zap.Float64("cost", costTime),
			)
		}
	}
}
