// This file projects normalized historical series into production Policy metric inputs.
package evaluation

import (
	"fmt"

	decisionmetrics "github.com/tidbcloud/cluster-service-ng/internal/capacity-planner/pkg/metrics"
)

// toPolicyMetrics converts each historical series to the latest per-instance
// sample available at the decision point.
func toPolicyMetrics(series []MetricSeries) []decisionmetrics.Metrics {
	metrics := make([]decisionmetrics.Metrics, 0)
	metricIndexes := make(map[string]int)

	for i := range series {
		index, ok := metricIndexes[series[i].Name]
		if !ok {
			index = len(metrics)
			metricIndexes[series[i].Name] = index
			metrics = append(metrics, decisionmetrics.Metrics{})
		}

		latest := series[i].Samples[len(series[i].Samples)-1]
		metrics[index].Series = append(metrics[index].Series, toPolicyTimeSeries(&series[i], latest))
	}

	return metrics
}

func toProjectedPolicyMetrics(series []MetricSeries, mappings []PolicyMetricMapping) ([]decisionmetrics.Metrics, error) {
	byName := make(map[string][]MetricSeries)
	for i := range series {
		byName[series[i].Name] = append(byName[series[i].Name], series[i])
	}

	metrics := make([]decisionmetrics.Metrics, 0, len(mappings))
	for i := range mappings {
		mapping := &mappings[i]
		source := byName[mapping.SourceMetric]
		if len(source) == 0 {
			return nil, fmt.Errorf("evaluation: policy source metric %q is missing", mapping.SourceMetric)
		}

		metric := decisionmetrics.Metrics{Series: make([]decisionmetrics.TimeSeries, 0, len(source))}
		for j := range source {
			latest := source[j].Samples[len(source[j].Samples)-1]
			metric.Series = append(metric.Series, toPolicyTimeSeries(&source[j], latest))
		}
		metrics = append(metrics, metric)
	}
	return metrics, nil
}

func toPolicyTimeSeries(series *MetricSeries, sample MetricSample) decisionmetrics.TimeSeries {
	metric := decisionmetrics.TimeSeries{
		Samples: []decisionmetrics.Sample{{Timestamp: sample.Timestamp, Value: sample.Value}},
	}
	if instance := series.Labels[metricInstanceLabel]; instance != "" {
		metric.Ref = &decisionmetrics.Reference{Name: instance}
	}
	return metric
}
