// SPDX-License-Identifier: Apache-2.0
//
// Copyright The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build windows

package textfile

import (
	"io"
	"strings"
	"testing"

	"github.com/dimchansky/utfbom"
	dto "github.com/prometheus/client_model/go"
)

func TestCRFilter(t *testing.T) {
	t.Parallel()

	sr := strings.NewReader("line 1\r\nline 2")
	cr := carriageReturnFilteringReader{r: sr}

	b, err := io.ReadAll(cr)
	if err != nil {
		t.Error(err)
	}

	if string(b) != "line 1\nline 2" {
		t.Errorf("Unexpected output %q", b)
	}
}

func TestCheckBOM(t *testing.T) {
	t.Parallel()

	testdata := []struct {
		encoding utfbom.Encoding
		err      string
	}{
		{utfbom.Unknown, ""},
		{utfbom.UTF8, ""},
		{utfbom.UTF16BigEndian, "UTF16BigEndian"},
		{utfbom.UTF16LittleEndian, "UTF16LittleEndian"},
		{utfbom.UTF32BigEndian, "UTF32BigEndian"},
		{utfbom.UTF32LittleEndian, "UTF32LittleEndian"},
	}
	for _, d := range testdata {
		err := checkBOM(d.encoding)
		if d.err == "" && err != nil {
			t.Error(err)
		}

		if d.err != "" && err == nil {
			t.Errorf("Missing expected error %s", d.err)
		}

		if err != nil && !strings.Contains(err.Error(), d.err) {
			t.Error(err)
		}
	}
}

func TestDuplicateMetricEntry(t *testing.T) {
	t.Parallel()

	metric_name := "windows_sometest"
	metric_help := "This is a Test."
	metric_type := dto.MetricType_GAUGE

	gauge_value := 1.0

	gauge := dto.Gauge{
		Value: &gauge_value,
	}

	label1_name := "display_name"
	label1_value := "foobar"

	label1 := dto.LabelPair{
		Name:  &label1_name,
		Value: &label1_value,
	}

	label2_name := "display_version"
	label2_value := "13.4.0"

	label2 := dto.LabelPair{
		Name:  &label2_name,
		Value: &label2_value,
	}

	metric1 := dto.Metric{
		Label: []*dto.LabelPair{&label1, &label2},
		Gauge: &gauge,
	}

	metric2 := dto.Metric{
		Label: []*dto.LabelPair{&label1, &label2},
		Gauge: &gauge,
	}

	duplicate := dto.MetricFamily{
		Name:   &metric_name,
		Help:   &metric_help,
		Type:   &metric_type,
		Metric: []*dto.Metric{&metric1, &metric2},
	}

	duplicateFamily := make([]*dto.MetricFamily, 0, 1)

	duplicateFamily = append(duplicateFamily, &duplicate)

	// Ensure detection for duplicate metrics
	if !duplicateMetricEntry(duplicateFamily) {
		t.Errorf("Duplicate not found in duplicateFamily")
	}

	label3_name := "test"
	label3_value := "1.0"

	label3 := dto.LabelPair{
		Name:  &label3_name,
		Value: &label3_value,
	}
	metric3 := dto.Metric{
		Label: []*dto.LabelPair{&label1, &label2, &label3},
		Gauge: &gauge,
	}

	differentLabels := dto.MetricFamily{
		Name:   &metric_name,
		Help:   &metric_help,
		Type:   &metric_type,
		Metric: []*dto.Metric{&metric1, &metric3},
	}

	duplicateFamily = make([]*dto.MetricFamily, 0, 1)
	duplicateFamily = append(duplicateFamily, &differentLabels)

	// Additional label on second metric should not be cause for duplicate detection
	if duplicateMetricEntry(duplicateFamily) {
		t.Errorf("Unexpected duplicate found in differentLabels")
	}

	label4_value := "2.0"

	label4 := dto.LabelPair{
		Name:  &label3_name,
		Value: &label4_value,
	}
	metric4 := dto.Metric{
		Label: []*dto.LabelPair{&label1, &label2, &label4},
		Gauge: &gauge,
	}

	differentValues := dto.MetricFamily{
		Name:   &metric_name,
		Help:   &metric_help,
		Type:   &metric_type,
		Metric: []*dto.Metric{&metric3, &metric4},
	}
	duplicateFamily = make([]*dto.MetricFamily, 0, 1)
	duplicateFamily = append(duplicateFamily, &differentValues)

	// Additional label with different values metric should not be cause for duplicate detection
	if duplicateMetricEntry(duplicateFamily) {
		t.Errorf("Unexpected duplicate found in differentValues")
	}
}
