package gardener

import (
	"context"

	"github.com/prometheus/client_golang/prometheus"
	"sigs.k8s.io/controller-runtime/pkg/client"
	logf "sigs.k8s.io/controller-runtime/pkg/log"

	shootapi "github.com/tidbcloud/infra-api/pkg/gardener/core/apis/v1beta1"
)

var logger = logf.Log.WithName("garderer-metrics")

const shootStatusKey = "shoot.gardener.cloud/status"

var (
	InfraResourcesShootInfo = prometheus.NewDesc(
		prometheus.BuildFQName("infra", "gardener_resources", "shoot_info"),
		"Information and status of infra cluster.",
		[]string{"name", "namespace", "region", "hibernated", "provider", "tenant", "project", "status"},
		nil)
)

type MetricsCollector struct {
	gardenCli client.Client
}

func NewMetricsCollector(gardenCli client.Client) *MetricsCollector {
	return &MetricsCollector{
		gardenCli: gardenCli,
	}
}

func (collector *MetricsCollector) Describe(ch chan<- *prometheus.Desc) {
	ch <- InfraResourcesShootInfo
}

func (collector *MetricsCollector) Collect(ch chan<- prometheus.Metric) {
	cli := collector.gardenCli
	ctx := context.Background()

	if err := collectShootMetrics(ctx, cli, ch); err != nil {
		logger.Error(err, "collect shoot metrics failed")
		return
	}
}

func collectShootMetrics(ctx context.Context, cli client.Client, ch chan<- prometheus.Metric) error {
	var isHibernated string
	shoots := shootapi.ShootList{}
	if err := cli.List(ctx, &shoots); err != nil {
		return err
	}

	for _, shoot := range shoots.Items {
		if !shoot.Status.IsHibernated {
			isHibernated = "false"
		} else {
			isHibernated = "true"
		}

		ch <- prometheus.MustNewConstMetric(
			InfraResourcesShootInfo,
			prometheus.GaugeValue,
			1.0,
			shoot.Name,
			shoot.Namespace,
			shoot.Spec.Region,
			isHibernated,
			shoot.Spec.CloudProfileName,
			shoot.GetLabels()["tenant"],  // Seems Shoot get this tag from Network dynamically, so hardcode it here
			shoot.GetLabels()["project"], // Seems Shoot get this tag from Network dynamically, so hardcode it here
			shoot.GetLabels()[shootStatusKey],
		)
	}
	return nil
}
