package handler

import (
	"context"

	"github.com/pingcap/log"
	"github.com/tidbcloud/observability/o11ymetering/pkg/common/constants"
	"github.com/tidbcloud/observability/o11ymetering/pkg/common/models"
	"github.com/tidbcloud/observability/o11ymetering/pkg/facade"
	"github.com/tidbcloud/observability/pkg/common/configs"
	"go.uber.org/zap"
)

type DedicatedDataplaneMetricCollection struct {
	Env constants.BizEnv
}

func (d DedicatedDataplaneMetricCollection) Build(ctx context.Context, period string) (models.StatisticTask, error) {
	return models.StatisticTask{
		Region:         configs.GetServiceInfo().Region,
		StatisticClass: constants.MetricsCollection,
		MeteringGroup:  constants.DedicatedDataplane,
		Env:            d.Env,
		Period:         period,
		State:          constants.StatePending,
	}, nil
}

var dedicatedMetricQuery = `sum(scrape_samples_scraped{tenant!=""})` + queryByLabels
var dedicatedMetricTopsqlQuery = `sum(rate(vector_component_received_events_count_sum{component_type="topsql"}))` + perClusterQueryByLabels

func (d DedicatedDataplaneMetricCollection) Execute(ctx context.Context, task models.StatisticTask) ([]*models.StatisticRecord, error) {
	// get metrics_timeseries_count of common-metrics from seed cluster
	infraClusters, err := facade.GetO11yMetaQuery().ListDedicatedK8sInfraClusters(ctx, task.Env)
	if err != nil {
		log.Error("failed to list dedicated k8s infra clusters", zap.Error(err))
		return []*models.StatisticRecord{}, err
	}

	var records []*models.StatisticRecord
	for _, cluster := range infraClusters {
		resp, err := facade.GetO11yMetricsQuery().QueryO11yMetricsInstant(ctx, configs.GetServiceInfo().Vendor, configs.GetServiceInfo().Region, cluster.ID, convertPeriodToTimestamp(task.Period), dedicatedMetricQuery, task.Env)

		if err != nil {
			return nil, err
		}
		recs := convertMetricCollectionRespToRecords(constants.MetricsTimeseriesCount, constants.Metrics, resp, task)

		records = append(records, recs...)
	}

	// get metrics_timeseries_count of topsql from per-cluster vector
	rs, topsqlErr := d.appendPerClusterTopsql(ctx, task)

	if topsqlErr != nil {
		return nil, topsqlErr
	}

	records = append(records, rs...)
	return records, nil
}

func (d DedicatedDataplaneMetricCollection) appendPerClusterTopsql(ctx context.Context, task models.StatisticTask) ([]*models.StatisticRecord, error) {
	clusters, err := facade.GetO11yMetaQuery().ListO11yDedicatedClusters(ctx, task.Env)
	if err != nil {
		return []*models.StatisticRecord{}, err
	}

	var records []*models.StatisticRecord

	for _, cluster := range clusters {
		resp, err := facade.GetO11yMetricsQuery().QueryO11yMetricsInstant(ctx, configs.GetServiceInfo().Vendor, configs.GetServiceInfo().Region, cluster.ID, convertPeriodToTimestamp(task.Period), dedicatedMetricTopsqlQuery, task.Env)

		if err != nil {
			return nil, err
		}

		records = append(records, convertMetricCollectionRespToRecords(constants.MetricsTimeseriesCount, constants.Metrics, resp, task)...)
	}
	return records, nil
}
