package api_test

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

	"github.com/stretchr/testify/require"
	"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/api"
	"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/config"
	"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/metric"
	"github.com/thomaspoignant/go-feature-flag/cmd/relayproxy/service"
	"github.com/thomaspoignant/go-feature-flag/notifier"
	"go.uber.org/zap"
)

func TestPprofEndpointsStarts(t *testing.T) {
	type test struct {
		name               string
		MonitoringPort     int
		Debug              bool
		EnablePprof        bool
		expectedStatusCode int
	}
	tests := []test{
		{
			name:               "pprof available in proxy port",
			Debug:              true,
			expectedStatusCode: http.StatusOK,
		},
		{
			name:               "pprof available in monitoring port",
			Debug:              true,
			MonitoringPort:     1032,
			expectedStatusCode: http.StatusOK,
		},
		{
			name:               "pprof not available if debug not enabled",
			Debug:              false,
			MonitoringPort:     1032,
			expectedStatusCode: http.StatusNotFound,
		},
		{
			name:               "pprof available when enablePprof is true",
			Debug:              false,
			EnablePprof:        true,
			MonitoringPort:     1032,
			expectedStatusCode: http.StatusOK,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			z, err := zap.NewProduction()
			require.NoError(t, err)
			c := &config.Config{
				Retriever: &config.RetrieverConf{
					Kind: "file",
					Path: "../../../testdata/flag-config.yaml",
				},
				MonitoringPort: tt.MonitoringPort,
				ListenPort:     1031,
				Debug:          tt.Debug,
				EnablePprof:    tt.EnablePprof,
			}

			goff, err := service.NewGoFeatureFlagClient(c, z, []notifier.Notifier{})
			require.NoError(t, err)
			apiServer := api.New(c, service.Services{
				MonitoringService:    service.NewMonitoring(goff),
				WebsocketService:     service.NewWebsocketService(),
				GOFeatureFlagService: goff,
				Metrics:              metric.Metrics{},
			}, z)

			portToCheck := c.ListenPort
			if tt.MonitoringPort != 0 {
				portToCheck = tt.MonitoringPort
			}

			go apiServer.Start()
			defer apiServer.Stop(context.Background())
			time.Sleep(1 * time.Second) // waiting for the apiServer to start
			resp, err := http.Get(fmt.Sprintf("http://localhost:%d/debug/pprof/heap", portToCheck))
			require.NoError(t, err)
			require.Equal(t, tt.expectedStatusCode, resp.StatusCode)
		})
	}
}
