package datasource

import (
	"errors"
	"strconv"

	"github.com/prometheus/prometheus/prompb"
)

type InsertActiveQPSParam struct {
	ClusterID string  `json:"cluster_id"`
	OrgID     string  `json:"org_id"` // clinic org_id
	StartUnix int64   `json:"start_unix"`
	EndUnix   int64   `json:"end_unix"`
	MaxQPS    float64 `json:"max_qps"`
	Threshold uint64  `json:"threshold"`
}

func (param *InsertActiveQPSParam) Validate() error {
	if param.ClusterID == "" {
		return errors.New("param.cluster_id is empty")
	}
	if param.OrgID == "" {
		return errors.New("param.org_id is empty")
	}
	if _, err := strconv.ParseUint(param.OrgID, 10, 64); err != nil {
		return err
	}
	if param.EndUnix <= param.StartUnix {
		return errors.New("param.end_unix and param.start_unix is invalid")
	}
	if param.MaxQPS == 0 {
		return errors.New("param.max_qps is empty")
	}
	if param.Threshold != 1 && param.Threshold != 100 && param.Threshold != 10000 {
		return errors.New("param.threshold is empty")
	}
	return nil
}

func (param *InsertActiveQPSParam) GetDurationSeconds() int64 {
	if param.EndUnix <= param.StartUnix {
		return 0
	}
	return param.EndUnix - param.StartUnix
}

func (param *InsertActiveQPSParam) GetStarUnixMillis() int64 {
	return param.StartUnix * 1e3
}

// clusterMeta is used to pass extra meta info between func calling to set label values
type clusterMeta struct {
	clusterName string
	region      string
	deployType  string
	tenantID    string
	tenantName  string
}

func (param *InsertActiveQPSParam) ToActiveDurationSeries(meta *clusterMeta) *prompb.TimeSeries {
	labels := param.genLabels(metricsNameActiveDuration, meta)
	ts := &prompb.TimeSeries{
		Labels: labels,
		Samples: []prompb.Sample{
			{
				Timestamp: param.GetStarUnixMillis(),
				Value:     float64(param.GetDurationSeconds()),
			},
		},
	}
	return ts
}

func (param *InsertActiveQPSParam) ToMaxQPSSeries(meta *clusterMeta) *prompb.TimeSeries {
	labels := param.genLabels(metricsNameMaxQPS, meta)
	ts := &prompb.TimeSeries{
		Labels: labels,
		Samples: []prompb.Sample{
			{
				Timestamp: param.GetStarUnixMillis(),
				Value:     param.MaxQPS,
			},
		},
	}
	return ts
}

func (param *InsertActiveQPSParam) genLabels(metricsName string, meta *clusterMeta) []prompb.Label {
	return []prompb.Label{
		{
			Name:  "__name__",
			Value: metricsName,
		},
		{
			Name:  "cluster_id",
			Value: param.ClusterID,
		},
		{
			Name:  "cluster_name",
			Value: meta.clusterName,
		},
		{
			Name:  "deploy_type",
			Value: meta.deployType,
		},
		{
			Name:  "org_id",
			Value: param.OrgID,
		},
		{
			Name:  "region",
			Value: meta.region,
		},
		{
			Name:  "tenant_id",
			Value: meta.tenantID,
		},
		{
			Name:  "tenant_name",
			Value: meta.tenantName,
		},
		{
			Name:  "threshold",
			Value: strconv.FormatUint(param.Threshold, 10),
		},
	}
}

type BatchInsertActiveQPSParam struct {
	Items []InsertActiveQPSParam `json:"items"`
}

func (param *BatchInsertActiveQPSParam) Validate() error {
	for _, item := range param.Items {
		if err := item.Validate(); err != nil {
			return err
		}
	}
	return nil
}
