package router

import (
	"os"
	"time"

	"github.com/prometheus/client_golang/prometheus"
	pbm "github.com/tidbcloud/aws-shared-provider/pbgen/manager"
	"github.com/tidbcloud/aws-shared-provider/pkg/gateway/metrics"
	"go.uber.org/zap"
)

const poolBackendInterval = time.Minute

func (r *Router) pollBackendLoop() {
	ticker := time.NewTicker(poolBackendInterval)
	defer ticker.Stop()
	for {
		select {
		case <-ticker.C:
			r.poll()
			r.updateMetrics()
		case <-r.quit:
			return
		}
	}
}

func (r *Router) poll() {
	start := time.Now()
	resp, err := r.grpcClient.GetBackendV2(r.grpcCtx, &pbm.GetBackendRequestV2{
		Token: r.token, GatewayHostname: os.Getenv("HOSTNAME"),
	})
	if err != nil {
		r.logger.Error("poll from manager failed", zap.Error(err))
		return
	}
	for _, res := range resp.Responses {
		pods := make([]*Pod, 0)
		for _, be := range res.Backends {
			pods = append(pods, &Pod{IP: be.Ip, Name: be.PodName, TidbPool: res.TidbPool})
		}
		err = r.cache.set(&Backend{
			TidbPool:    res.TidbPool,
			ModRevision: res.ModRevision,
			Replicas:    int(res.Replicas),
			Pods:        pods,
		})
		// only log when backends are updated
		if err == nil {
			r.logger.Info("poll set backend success", zap.Any("backend", res), zap.Duration("duration", time.Since(start)))
		}
	}
}

func (r *Router) updateMetrics() {
	// set connection count metrics
	metrics.ConnectionGauge.WithLabelValues(r.clusterID, r.token).Set(float64(r.ConnCount()))
	// set actual TiDB replicas metrics
	metrics.TiDBReplicasGauge.WithLabelValues(r.clusterID, r.token).Set(float64(len(r.GetBackendIPs())))
	// set backend pods name metrics
	pods := r.cache.listAllPods()
	metrics.BackendPodsGauge.DeletePartialMatch(prometheus.Labels{"cluster_id": r.clusterID})
	for _, pod := range pods {
		metrics.BackendPodsGauge.WithLabelValues(r.clusterID, r.token, pod.TidbPool, pod.Name).Set(1)
	}
}
