package api

import (
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/gin-gonic/gin"
	"github.com/tidbcloud/account/commons/config"
	"github.com/tidbcloud/pkgv2/auth/auth0"
	"github.com/tj/assert"
)

func BillingProxyWrapper(isAdmin bool) gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Set(string(auth0.AuthTokenClaimKey), "unittest@pingcap.com")
		BillingProxy(c)
	}
}

func TestBillingProxyRedirectNotExists(t *testing.T) {
	assert := assert.New(t)
	router := gin.New()
	router.Any("/api_proxy/billing/*any", BillingProxyWrapper(false))
	testServer := gin.New()
	// use random port
	listener, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		panic(err)
	}
	config.Global().BillingConfig.Billing2BaseURL = "http://" + listener.Addr().String()
	go http.Serve(listener, testServer) //nolint
	frontend := httptest.NewServer(router)
	defer frontend.Close()
	req, err := http.NewRequest("GET", frontend.URL+"/api_proxy/billing/api/v1/billing/tenants/10/invoices", nil)
	assert.NoError(err)
	frontendClient := frontend.Client()
	result, err := frontendClient.Do(req)
	assert.NoError(err)
	_ = assert
	assert.Equal(result.StatusCode, 404)
}

func TestBillingProxy(t *testing.T) {
	assert := assert.New(t)
	router := gin.New()
	// router.Use(MustHaveAdminPermissions())
	router.Any("/api_proxy/billing/*any", BillingProxyWrapper(false))
	testServer := gin.New()
	testServer.GET("/api/v1/billing/tenants/10/invoices", func(c *gin.Context) {
		c.String(http.StatusOK, "test_res")
	})
	// use random port
	listener, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		panic(err)
	}
	config.Global().BillingConfig.Billing2BaseURL = "http://" + listener.Addr().String()
	go http.Serve(listener, testServer) //nolint
	frontend := httptest.NewServer(router)
	defer frontend.Close()
	req, err := http.NewRequest("GET", frontend.URL+"/api_proxy/billing/api/v1/billing/tenants/10/invoices", nil)
	assert.NoError(err)
	frontendClient := frontend.Client()
	result, err := frontendClient.Do(req)
	assert.NoError(err)
	_ = assert
	body, err := ioutil.ReadAll(result.Body)
	assert.NoError(err)
	assert.Equal(string(body), "test_res")
	assert.Equal(result.StatusCode, 200)
}

func TestBillingProxyPermission(t *testing.T) {
	assert := assert.New(t)
	router := gin.New()
	router.Use(MustHaveAdminPermissions())
	router.Any("/api_proxy/billing/*any", BillingProxyWrapper(false))
	testServer := gin.New()
	testServer.GET("/api/v1/billing/tenants/10/invoices", func(c *gin.Context) {
		c.String(http.StatusOK, "test_res")
	})
	// use random port
	listener, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		panic(err)
	}
	config.Global().BillingConfig.Billing2BaseURL = "http://" + listener.Addr().String()
	go http.Serve(listener, testServer) //nolint
	frontend := httptest.NewServer(router)
	defer frontend.Close()
	req, err := http.NewRequest("GET", frontend.URL+"/api_proxy/billing/api/v1/billing/tenants/10/invoices", nil)
	assert.NoError(err)
	frontendClient := frontend.Client()
	result, err := frontendClient.Do(req)
	assert.NoError(err)
	_ = assert
	_, err = ioutil.ReadAll(result.Body)
	assert.NoError(err)
	assert.Equal(result.StatusCode, 401)
}
