// 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.

package vultr

import (
	"context"
	"fmt"
	"net/url"
	"testing"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/model"
	"github.com/prometheus/common/promslog"
	"github.com/stretchr/testify/require"

	"github.com/prometheus/prometheus/discovery"
)

type VultrSDTestSuite struct {
	Mock *SDMock
}

func (s *VultrSDTestSuite) TearDownSuite() {
	s.Mock.ShutdownServer()
}

func (s *VultrSDTestSuite) SetupTest(t *testing.T) {
	s.Mock = NewSDMock(t)
	s.Mock.Setup()

	s.Mock.HandleInstanceList()
}

func TestVultrSDRefresh(t *testing.T) {
	sdMock := &VultrSDTestSuite{}
	sdMock.SetupTest(t)
	t.Cleanup(sdMock.TearDownSuite)

	cfg := DefaultSDConfig
	cfg.HTTPClientConfig.BearerToken = APIKey

	reg := prometheus.NewRegistry()
	refreshMetrics := discovery.NewRefreshMetrics(reg)
	metrics := cfg.NewDiscovererMetrics(reg, refreshMetrics)
	require.NoError(t, metrics.Register())
	defer metrics.Unregister()
	defer refreshMetrics.Unregister()

	d, err := NewDiscovery(&cfg, discovery.DiscovererOptions{
		Logger:  promslog.NewNopLogger(),
		Metrics: metrics,
		SetName: "vultr",
	})
	require.NoError(t, err)
	endpoint, err := url.Parse(sdMock.Mock.Endpoint())
	require.NoError(t, err)
	d.client.BaseURL = endpoint

	ctx := context.Background()
	tgs, err := d.refresh(ctx)
	require.NoError(t, err)

	require.Len(t, tgs, 1)

	tg := tgs[0]
	require.NotNil(t, tg)
	require.NotNil(t, tg.Targets)
	require.Len(t, tg.Targets, 3)

	for i, k := range []model.LabelSet{
		{
			"__address__":                                model.LabelValue("149.28.234.27:80"),
			"__meta_vultr_instance_id":                   model.LabelValue("dbdbd38c-9884-4c92-95fe-899e50dee717"),
			"__meta_vultr_instance_label":                model.LabelValue("np-2-eae38a19b0f3"),
			"__meta_vultr_instance_os":                   model.LabelValue("Marketplace"),
			"__meta_vultr_instance_os_id":                model.LabelValue("426"),
			"__meta_vultr_instance_region":               model.LabelValue("ewr"),
			"__meta_vultr_instance_plan":                 model.LabelValue("vhf-2c-4gb"),
			"__meta_vultr_instance_main_ip":              model.LabelValue("149.28.234.27"),
			"__meta_vultr_instance_internal_ip":          model.LabelValue("10.1.96.5"),
			"__meta_vultr_instance_main_ipv6":            model.LabelValue(""),
			"__meta_vultr_instance_features":             model.LabelValue(",backups,"),
			"__meta_vultr_instance_tags":                 model.LabelValue(",tag1,tag2,tag3,"),
			"__meta_vultr_instance_hostname":             model.LabelValue("np-2-eae38a19b0f3"),
			"__meta_vultr_instance_server_status":        model.LabelValue("ok"),
			"__meta_vultr_instance_vcpu_count":           model.LabelValue("2"),
			"__meta_vultr_instance_ram_mb":               model.LabelValue("4096"),
			"__meta_vultr_instance_disk_gb":              model.LabelValue("128"),
			"__meta_vultr_instance_allowed_bandwidth_gb": model.LabelValue("3000"),
		},
		{
			"__address__":                                model.LabelValue("45.63.1.222:80"),
			"__meta_vultr_instance_id":                   model.LabelValue("fccb117c-62f7-4b17-995d-a8e56dd30b33"),
			"__meta_vultr_instance_label":                model.LabelValue("np-2-fd0714b5fe42"),
			"__meta_vultr_instance_os":                   model.LabelValue("Marketplace"),
			"__meta_vultr_instance_os_id":                model.LabelValue("426"),
			"__meta_vultr_instance_region":               model.LabelValue("ewr"),
			"__meta_vultr_instance_plan":                 model.LabelValue("vhf-2c-4gb"),
			"__meta_vultr_instance_main_ip":              model.LabelValue("45.63.1.222"),
			"__meta_vultr_instance_internal_ip":          model.LabelValue("10.1.96.6"),
			"__meta_vultr_instance_main_ipv6":            model.LabelValue(""),
			"__meta_vultr_instance_hostname":             model.LabelValue("np-2-fd0714b5fe42"),
			"__meta_vultr_instance_server_status":        model.LabelValue("ok"),
			"__meta_vultr_instance_vcpu_count":           model.LabelValue("2"),
			"__meta_vultr_instance_ram_mb":               model.LabelValue("4096"),
			"__meta_vultr_instance_disk_gb":              model.LabelValue("128"),
			"__meta_vultr_instance_allowed_bandwidth_gb": model.LabelValue("3000"),
		},
		{
			"__address__":                                model.LabelValue("149.28.237.151:80"),
			"__meta_vultr_instance_id":                   model.LabelValue("c4e58767-f61b-4c5e-9bce-43761cc04868"),
			"__meta_vultr_instance_label":                model.LabelValue("np-2-d04e7829fa43"),
			"__meta_vultr_instance_os":                   model.LabelValue("Marketplace"),
			"__meta_vultr_instance_os_id":                model.LabelValue("426"),
			"__meta_vultr_instance_region":               model.LabelValue("ewr"),
			"__meta_vultr_instance_plan":                 model.LabelValue("vhf-2c-4gb"),
			"__meta_vultr_instance_main_ip":              model.LabelValue("149.28.237.151"),
			"__meta_vultr_instance_internal_ip":          model.LabelValue("10.1.96.7"),
			"__meta_vultr_instance_main_ipv6":            model.LabelValue(""),
			"__meta_vultr_instance_hostname":             model.LabelValue("np-2-d04e7829fa43"),
			"__meta_vultr_instance_server_status":        model.LabelValue("ok"),
			"__meta_vultr_instance_vcpu_count":           model.LabelValue("2"),
			"__meta_vultr_instance_ram_mb":               model.LabelValue("4096"),
			"__meta_vultr_instance_disk_gb":              model.LabelValue("128"),
			"__meta_vultr_instance_allowed_bandwidth_gb": model.LabelValue("3000"),
		},
	} {
		t.Run(fmt.Sprintf("item %d", i), func(t *testing.T) {
			require.Equal(t, k, tg.Targets[i])
		})
	}
}
