package handlers

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

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/require"

	clinic_internal_api "github.com/pingcap-inc/clinic/clinic_data_service/pkg/clinic-internal-api"
)

type fakeComponentsClient struct {
	orgID      uint64
	clusterID  string
	components []*clinic_internal_api.ResourcePoolComponent
	err        error
}

func (f *fakeComponentsClient) ListComponents(_ context.Context, orgID uint64, clusterID string) ([]*clinic_internal_api.ResourcePoolComponent, error) {
	f.orgID = orgID
	f.clusterID = clusterID
	return f.components, f.err
}

func componentsTestRouter(client componentsLister) *gin.Engine {
	gin.SetMode(gin.TestMode)
	router := gin.New()
	NewComponentsHandler(client).RegisterRoutes(router)
	return router
}

func TestComponentsHandlerIsThinClinicFacade(t *testing.T) {
	client := &fakeComponentsClient{components: []*clinic_internal_api.ResourcePoolComponent{{
		ID: "tidb-1", ComponentType: "tidb", CPU: 8, NodeCount: 2,
	}}}
	response := httptest.NewRecorder()
	request := httptest.NewRequest(http.MethodGet, "/data-proxy/api/v1/orgs/123/clusters/cluster-a/components", nil)
	request.Header.Set("Authorization", "must-not-be-forwarded")
	request.Header.Set("x-csrf-token", "must-not-enable-legacy-shape")
	componentsTestRouter(client).ServeHTTP(response, request)

	require.Equal(t, http.StatusOK, response.Code, response.Body.String())
	require.JSONEq(t, `[{"id":"tidb-1","component_type":"tidb","cpu":8,"memory_gi":0,"node_count":2,"max_node_count":0,"min_node_count":0,"storages":null,"version":"","phase":""}]`, response.Body.String())
	require.Equal(t, uint64(123), client.orgID)
	require.Equal(t, "cluster-a", client.clusterID)
}

func TestComponentsHandlerMapsOwnershipNotFound(t *testing.T) {
	client := &fakeComponentsClient{err: &clinic_internal_api.UpstreamError{StatusCode: http.StatusNotFound}}
	response := httptest.NewRecorder()
	componentsTestRouter(client).ServeHTTP(response, httptest.NewRequest(http.MethodGet,
		"/data-proxy/api/v1/orgs/123/clusters/missing/components", nil))
	require.Equal(t, http.StatusNotFound, response.Code)
}

func TestComponentsHandlerSupportsPublicAlias(t *testing.T) {
	client := &fakeComponentsClient{components: []*clinic_internal_api.ResourcePoolComponent{}}
	response := httptest.NewRecorder()
	componentsTestRouter(client).ServeHTTP(response, httptest.NewRequest(http.MethodGet,
		"/api/v1/orgs/123/data-proxy/clusters/cluster-a/components", nil))

	require.Equal(t, http.StatusOK, response.Code)
	require.Equal(t, uint64(123), client.orgID)
	require.Equal(t, "cluster-a", client.clusterID)
}
