package searchV2

import (
	"context"

	"github.com/blugelabs/bluge"
	"github.com/blugelabs/bluge/search"
	"github.com/blugelabs/bluge/search/aggregations"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"

	"github.com/grafana/grafana/pkg/infra/log"
	"github.com/grafana/grafana/pkg/infra/tracing"
)

type usageGauge struct {
	field string
	gauge *prometheus.GaugeVec
}

var (
	infoPanelUsage = promauto.NewGaugeVec(prometheus.GaugeOpts{
		Name:      "panel_type_usage",
		Help:      "a metric indicating how many panels across all dashboards use each plugin panel type",
		Namespace: "grafana",
	}, []string{"name"})

	infoDatasourceUsage = promauto.NewGaugeVec(prometheus.GaugeOpts{
		Name:      "panel_datasource_usage",
		Help:      "indicates how many panels across all dashboards reference each datasource type",
		Namespace: "grafana",
	}, []string{"name"})

	infoTransformerUsage = promauto.NewGaugeVec(prometheus.GaugeOpts{
		Name:      "panel_transformer_usage",
		Help:      "indicates how many panels use each transformer type",
		Namespace: "grafana",
	}, []string{"name"})

	panelUsage = []usageGauge{
		{field: documentFieldDSType, gauge: infoDatasourceUsage},
		{field: documentFieldPanelType, gauge: infoPanelUsage},
		{field: documentFieldTransformer, gauge: infoTransformerUsage},
	}
)

func updateUsageStats(ctx context.Context, reader *bluge.Reader, logger log.Logger, tracer tracing.Tracer) {
	ctx, span := tracer.Start(ctx, "searchV2.updateUsageStats")
	defer span.End()
	req := bluge.NewAllMatches(bluge.NewTermQuery("panel").SetField(documentFieldKind))
	for _, usage := range panelUsage {
		req.AddAggregation(usage.field, aggregations.NewTermsAggregation(search.Field(usage.field), 50))
	}

	// execute this search on the reader
	documentMatchIterator, err := reader.Search(ctx, req)
	if err != nil {
		logger.Error("Error executing search", "err", err)
		return
	}

	// need to iterate through the document matches, otherwise the aggregations are empty?
	match, err := documentMatchIterator.Next()
	for err == nil && match != nil {
		match, err = documentMatchIterator.Next()
	}

	aggs := documentMatchIterator.Aggregations()
	for _, usage := range panelUsage {
		bucket := aggs.Buckets(usage.field)
		for _, v := range bucket {
			if v.Name() == "" {
				continue
			}
			usage.gauge.WithLabelValues(v.Name()).Set(float64(v.Count()))
		}
	}
}
