package handler

import (
	"fmt"
	"strconv"
	"time"

	o11yconstants "github.com/tidbcloud/observability/pkg/common/constants"

	log "github.com/sirupsen/logrus"
	"github.com/tidbcloud/observability/o11ymetering/pkg/common/constants"
	"github.com/tidbcloud/observability/o11ymetering/pkg/common/models"
	"github.com/tidbcloud/observability/pkg/common/configs"
)

var queryByLabels = " by (tenant,project,tidb_cluster,tidbcloud_cluster,component,component_id,container,container_name,label_tidbcloud_cluster,label_component,label_project,label_tidbcloud_com_component)"
var perClusterQueryByLabels = " by (tenant,project,tidb_cluster,tidb_cluster_id,tidbcloud_cluster,component,component_id,container,container_name,label_tidbcloud_cluster,label_component,label_project,label_tidbcloud_com_component)"

func convertMetricCollectionRespToRecords(statisticName constants.StatisticName, category constants.Category, resp *models.O11yMetricsResponse, task models.StatisticTask) []*models.StatisticRecord {
	results := resp.Data.Result
	records := make([]*models.StatisticRecord, len(results))
	for i, result := range results {
		records[i] = &models.StatisticRecord{
			TaskID:         task.ID,
			Region:         configs.GetServiceInfo().Region,
			StatisticClass: task.StatisticClass,
			MeteringGroup:  task.MeteringGroup,
			Period:         task.Period,
			Env:            task.Env,
			StatisticName:  statisticName,

			ClusterMeta: models.ClusterMeta{
				Tenant:  getTenant(result.O11yMetricsLabelSet),
				Project: getProject(result.O11yMetricsLabelSet),
				Cluster: getCluster(result.O11yMetricsLabelSet),
			},
			Category:    category,
			SubCategory: getSubCategory(result.O11yMetricsLabelSet),
			Component:   getComponent(result.O11yMetricsLabelSet),
			Container:   getContainer(result.O11yMetricsLabelSet),
			Source:      "",
			Value:       convertValue(result.Value[1].(string)),
		}
	}
	return records
}

func getTenant(labelSet models.O11yMetricsLabelSet) string {
	if len(labelSet.Tenant) > 0 {
		return labelSet.Tenant
	}
	return "undefined"
}

func getProject(labelSet models.O11yMetricsLabelSet) string {
	if len(labelSet.Project) > 0 {
		return labelSet.Project
	}
	if len(labelSet.LabelProject) > 0 {
		return labelSet.LabelProject
	}
	return "undefined"
}

func getCluster(labelSet models.O11yMetricsLabelSet) string {
	if len(labelSet.TidbCluster) > 0 {
		return labelSet.TidbCluster
	}
	if len(labelSet.TidbCloudCluster) > 0 {
		return labelSet.TidbCloudCluster
	}
	if len(labelSet.TidbClusterID) > 0 {
		return labelSet.TidbClusterID
	}
	if len(labelSet.LabelTidbcloud_Cluster) > 0 {
		return labelSet.LabelTidbcloud_Cluster
	}
	return "undefined"
}

func getComponent(labelSet models.O11yMetricsLabelSet) string {
	if len(labelSet.Component) > 0 {
		return labelSet.Component
	}
	if len(labelSet.LabelComponent) > 0 {
		return labelSet.LabelComponent
	}
	if len(labelSet.LabelTidbcloud_ComComponent) > 0 {
		return labelSet.LabelTidbcloud_ComComponent
	}
	return "undefined"
}

/*
 * Label mapping relationships may be different.
 */
func getSubCategory(labelSet models.O11yMetricsLabelSet) string {
	if len(labelSet.ComponentID) > 0 {
		return labelSet.ComponentID
	}
	return "undefined"
}

func getContainer(labelSet models.O11yMetricsLabelSet) string {
	if len(labelSet.Container) > 0 {
		return labelSet.Container
	}
	if len(labelSet.ContainerName) > 0 {
		return labelSet.ContainerName
	}
	return "undefined"
}

func convertPeriodToTimestamp(period string) time.Time {
	loc, _ := time.LoadLocation("UTC")
	theTime, err := time.ParseInLocation("2006-01-02 15:04:05", period, loc)
	if err != nil {
		panic(err)
	}
	return theTime
}

func convertVendorToProvider(vendor string) string {
	if vendor == "aws" {
		return "eks"
	} else if vendor == "gcp" {
		return "gke"
	}
	panic("implement me")
}

func convertValue(value string) float64 {
	if len(value) == 0 {
		return 0
	}
	f, err := strconv.ParseFloat(value, 64)
	if err != nil {
		log.Errorf("convert sample value to float64 failed, value = %s", value)
		return 0
	}
	return f
}

var awsS3 = "aws_s3"
var gcpCloudStorage = "gcp_cloud_storage"

func renderS3ComponentType(query string) string {
	var a string
	if configs.GetServiceInfo().Vendor == string(o11yconstants.AWS) {
		a = awsS3
	} else if configs.GetServiceInfo().Vendor == string(o11yconstants.GCP) {
		a = gcpCloudStorage
	}
	return fmt.Sprintf(query, a)
}
