package prom

import (
	"bytes"
	"math"
	"strings"
	"testing"

	"github.com/prometheus/common/model"
	"github.com/stretchr/testify/assert"
)

func TestVecMetricPrometheusFormat(t *testing.T) {
	v := VecMetric{
		Name: "db_query_count",
		Help: "Number of queries by command",
		Type: "counter",
		Metrics: []*VecMetricElement{
			{
				Labels: []MetricLabel{{"command", "CreateTable"}},
				Value:  21,
			},
			{
				Labels: []MetricLabel{{"command", "other"}},
				Value:  1,
			},
			{
				Labels: []MetricLabel{{"command", "Replace"}},
				Value:  0,
			},
		},
	}
	output, err := encodeAsPrometheus(&v)
	assert.Nil(t, err)
	assert.Equal(t, strings.TrimSpace(`
# HELP db_query_count Number of queries by command
# TYPE db_query_count counter
db_query_count{command="CreateTable"} 21
db_query_count{command="other"} 1
db_query_count{command="Replace"} 0
`), strings.TrimSpace(output))

	v = VecMetric{
		Name: "foo_bar",
		Help: "Help messages",
		Type: "gauge",
		Metrics: []*VecMetricElement{
			{
				Labels: []MetricLabel{
					{"label1", "value1"},
					{"label2", "value2"},
					{"gt", "0.0"}},
				Value: 5.5,
			},
			{
				Labels: []MetricLabel{
					{"label1", "value3"},
					{"label2", "value4"},
					{"gt", "+inf"},
				},
				Value: 7,
			},
		},
	}
	output, err = encodeAsPrometheus(&v)
	assert.Nil(t, err)
	assert.Equal(t, strings.TrimSpace(`
# HELP foo_bar Help messages
# TYPE foo_bar gauge
foo_bar{label1="value1",label2="value2",gt="0.0"} 5.5
foo_bar{label1="value3",label2="value4",gt="+inf"} 7
`), strings.TrimSpace(output))
}

func TestNaN(t *testing.T) {
	v := SingleMetric{
		Name:  "foo",
		Help:  "Help messages",
		Type:  "counter",
		Value: model.SampleValue(math.NaN()),
	}

	output, err := encodeAsPrometheus(&v)
	assert.Nil(t, err)
	assert.Equal(t, strings.TrimSpace(`
# HELP foo Help messages
# TYPE foo counter
foo NaN
`), strings.TrimSpace(output))
}

func encodeAsPrometheus(m Metric) (string, error) {
	buf := bytes.Buffer{}
	if err := m.EncodePrometheusFormat(&buf); err != nil {
		return "", err
	}
	return buf.String(), nil
}
