package gcpquota

import (
	"context"
	"fmt"
	"testing"

	"github.com/go-logr/logr/testr"
	. "github.com/onsi/gomega"
	"github.com/prometheus/client_golang/prometheus"

	"github.com/tidbcloud/infra-provider/quota-exporter/config"
)

func TestExporterCollect(t *testing.T) {
	expectMetricCount := func(quotaCount, acctCount int) int {
		// quotaCount is the number of quotas fakeQuotaClient returns
		return quotaCount * acctCount * 2
	}

	cases := map[string]struct {
		acctCount int
		setup     func(*GCPQuotaExporter, *fakeQuotaClient, []config.GCPAccount)
		expect    func(*WithT, *GCPQuotaExporter, []prometheus.Metric)
	}{
		"normal": {
			acctCount: 2,
			setup: func(e *GCPQuotaExporter, cli *fakeQuotaClient, accounts []config.GCPAccount) {
				cli.quotas = []Quota{
					{Metric: "test"},
				}
				cli.err = nil
			},
			expect: func(g *WithT, e *GCPQuotaExporter, metrics []prometheus.Metric) {
				// check metrics
				g.Expect(metrics).To(HaveLen(expectMetricCount(1, 2)))
			},
		},
	}

	for name, c := range cases {
		t.Run(name, func(t *testing.T) {
			g := NewGomegaWithT(t)
			accounts := gcpAccounts(c.acctCount)
			quotaClient := &fakeQuotaClient{}
			cfg := &config.GCPQuotaExporterConfig{
				GCPAccounts: accounts,
			}
			_ = cfg.Complete()

			e := &GCPQuotaExporter{
				cfg:    cfg,
				logger: testr.New(t),
				client: quotaClient,
			}

			c.setup(e, quotaClient, accounts)

			ch := make(chan prometheus.Metric, 100)
			e.Collect(ch)
			close(ch)
			metrics := []prometheus.Metric{}
			for metric := range ch {
				metrics = append(metrics, metric)
			}

			c.expect(g, e, metrics)
		})
	}
}

type fakeQuotaClient struct {
	err    error
	quotas []Quota
}

func (c *fakeQuotaClient) QueryQuotas(ctx context.Context, project string) ([]Quota, error) {
	return c.quotas, c.err
}

func gcpAccounts(count int) []config.GCPAccount {
	accounts := []config.GCPAccount{}
	for i := 0; i < count; i++ {
		accounts = append(accounts, config.GCPAccount{
			ProjectID: fmt.Sprintf("%d", i),
		})
	}
	return accounts
}
