package monitoring

import (
	"net"
	"testing"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/stretchr/testify/require"
)

func Test_applyOptions(t *testing.T) {
	testListener, err := net.Listen("tcp", ":0")
	require.NoError(t, err)
	defer testListener.Close()

	checkDefaultListener := func(t *testing.T, f listenerFactory) {
		gotListener, err := f()
		require.Exactly(t, nil, gotListener)
		require.NoError(t, err)
	}

	isTestListener := func(t *testing.T, f listenerFactory) {
		gotListener, err := f()
		require.NoError(t, err)
		require.Exactly(t, testListener, gotListener)
	}

	isTCPListener := func(t *testing.T, f listenerFactory) {
		gotListener, err := f()
		require.NoError(t, err)
		require.IsType(t, &net.TCPListener{}, gotListener)
	}

	tests := []struct {
		name                     string
		opts                     []Option
		wantListenerCheck        func(t *testing.T, f listenerFactory)
		wantbuildInfoGaugeLabels prometheus.Labels
		wantVersion              string
	}{
		{
			name:              "empty",
			opts:              nil,
			wantListenerCheck: checkDefaultListener,
		},
		{
			name:              "with_listener",
			opts:              []Option{WithListener(testListener)},
			wantListenerCheck: isTestListener,
		},
		{
			name:              "with_listen_address",
			opts:              []Option{WithListenerAddress(":0")},
			wantListenerCheck: isTCPListener,
		},
		{
			name:                     "with_build_information",
			opts:                     []Option{WithBuildInformation("1.0.0", "2018-01-02T00:00:00Z")},
			wantListenerCheck:        checkDefaultListener,
			wantbuildInfoGaugeLabels: prometheus.Labels{"built": "2018-01-02T00:00:00Z", "version": "1.0.0"},
			wantVersion:              "1.0.0",
		},
		{
			name:                     "with_build_extra_labels",
			opts:                     []Option{WithBuildExtraLabels(map[string]string{"git_version": "2.0.0"})},
			wantListenerCheck:        checkDefaultListener,
			wantbuildInfoGaugeLabels: prometheus.Labels{"git_version": "2.0.0"},
		},
		{
			name: "with_build_information_and_extra_labels",
			opts: []Option{
				WithBuildInformation("1.0.0", "2018-01-02T00:00:00Z"),
				WithBuildExtraLabels(map[string]string{"git_version": "2.0.0"}),
			},
			wantListenerCheck: checkDefaultListener,
			wantbuildInfoGaugeLabels: prometheus.Labels{
				"built":       "2018-01-02T00:00:00Z",
				"version":     "1.0.0",
				"git_version": "2.0.0",
			},
			wantVersion: "1.0.0",
		},
		{
			name: "combined",
			opts: []Option{
				WithListenerAddress(":0"),
				WithBuildInformation("1.0.0", "2018-01-02T00:00:00Z"),
				WithBuildExtraLabels(map[string]string{"git_version": "2.0.0"}),
			},
			wantListenerCheck: isTCPListener,
			wantbuildInfoGaugeLabels: prometheus.Labels{
				"built":       "2018-01-02T00:00:00Z",
				"version":     "1.0.0",
				"git_version": "2.0.0",
			},
			wantVersion: "1.0.0",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := applyOptions(tt.opts)
			tt.wantListenerCheck(t, got.listenerFactory)
			require.Equal(t, tt.wantVersion, got.version)

			if tt.wantbuildInfoGaugeLabels == nil {
				require.Equal(t, prometheus.Labels{}, got.buildInfoGaugeLabels)
			} else {
				require.Equal(t, tt.wantbuildInfoGaugeLabels, got.buildInfoGaugeLabels)
			}
		})
	}
}
