package tidbreclaimer

import (
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	"github.com/go-logr/logr"
	. "github.com/onsi/gomega"
	"github.com/pingcap/errors"
	"github.com/tidbcloud/aws-shared-provider/pkg/utils/query"
	"sigs.k8s.io/controller-runtime/pkg/log"
)

const (
	errorData = `{"status":"error","errorType":"bad_data","error":"invalid parameter 'query': parse error"}`
	emptyData = `{"status":"success","data":{"resultType":"matrix","result":[]}}`
	hasData   = `{"status":"success","data":{"resultType":"matrix","result":[` +
		`{"metric":{"instance":"pod1"},"value":[1667460382,"0"]},` +
		`{"metric":{"instance":"pod2"},"value":[1667460382,"0"]},` +
		`{"metric":{"instance":"pod3"},"value":[1667460382,"0"]}]}}`
)

func TestTidbReclaimer_QueryInactivePods(t *testing.T) {
	tests := []struct {
		name        string
		retData     string
		expectedErr error
		expectedRes []string
	}{
		{
			name:        "get 0 inactive pods with error",
			retData:     errorData,
			expectedErr: errors.Errorf(`query failed: "invalid parameter 'query': parse error"`),
		}, {
			name:        "get 0 inactive pods with empty res",
			retData:     emptyData,
			expectedRes: nil,
		}, {
			name:        "get 3 inactive pods with res",
			retData:     hasData,
			expectedRes: []string{"pod1", "pod2", "pod3"},
		},
	}

	var data string
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, data)
	}))
	defer ts.Close()
	querier := query.NewPromQueryer(nil, ts.URL)

	tr := &TidbReclaimer{
		Logger:            logr.New(log.NullLogSink{}),
		ctx:               context.Background(),
		gcInterval:        time.Minute * 30,
		tidbPoolNamespace: "tidb-pool",
		o11yQuerier:       querier,
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			g := NewGomegaWithT(t)
			data = tt.retData
			pods, err := tr.QueryInactivePods()
			if tt.expectedErr == nil {
				g.Expect(err).To(Succeed())
				g.Expect(pods).To(Equal(tt.expectedRes))
			} else {
				g.Expect(err).To(MatchError(tt.expectedErr.Error()))
			}
		})
	}
}
