package tests

import (
	"encoding/json"
	"fmt"
	"net/http"
	"testing"

	"github.com/gin-gonic/gin"
	"github.com/pingcap/dbaas/billing2/api"
	"github.com/pingcap/dbaas/billing2/config"
	"github.com/pingcap/dbaas/billing2/db/entity"
	"github.com/pingcap/dbaas/billing2/forms"
	"github.com/pingcap/dbaas/billing2/middleware"
	"github.com/pingcap/dbaas/billing2/model/billing"
	"github.com/pingcap/dbaas/billing2/model/billingconfig"
	"github.com/pingcap/dbaas/billing2/model/marketing/unit_filter"
	"github.com/pingcap/dbaas/billing2/utils/ginutils"
	"github.com/pingcap/dbaas/billing2/utils/tests"
	"github.com/pingcap/dbaas/billing2/utils/tests/datainit"
	"github.com/shopspring/decimal"
	"github.com/stretchr/testify/suite"
)

type OpenAPITestSuite struct {
	tests.BillingTestSuite
	router *gin.Engine
}

func (suite *OpenAPITestSuite) SetupTest() {
	suite.BillingTestSuite.SetupTest()
	suite.router = gin.New()
	suite.router.Use(ginutils.ErrorMiddleWare)
	billingOpenAPIGroup := suite.router.Group("/v1beta1")
	wsOpenAPI := ginutils.MyRoute{Route: billingOpenAPIGroup}
	wsOpenAPI.Use(
		middleware.OpenAPIPathNormalize(suite.router),
	)
	api.RegisterOpenAPIRouter(wsOpenAPI)

	mspBillingOpenAPIGroup := suite.router.Group("/v1beta1/msp")
	wsMspOpenAPI := ginutils.MyRoute{Route: mspBillingOpenAPIGroup}
	wsMspOpenAPI.Use(
		middleware.OpenAPIPathNormalize(suite.router),
	)
	api.RegisterMSPOpenAPIRouter(wsMspOpenAPI)
	mockCentral()
	_, err := (&billing.UnitModel{}).CreateUnit(&forms.UnitInfo{
		UnitKey: datainit.TestUnit,
	})
	assert := suite.Assert()
	assert.NoError(err)
	generalUnitFilter, err := (&unit_filter.Model{}).CreateUnitFilter(&forms.UnitFilter{
		UnitFilterSlim: forms.UnitFilterSlim{Name: "General", Description: "General"},
		General:        true,
	})
	config.Get().Set(config.GeneralCreditTypeID, generalUnitFilter.FilterID)
	assert.NoError(err)
	_, err = (&billing.PackageModel{}).CreatePackage(&forms.PackageInfo{
		UnitPrices: forms.UnitPrices{
			datainit.TestUnit: {Price: decimal.NewFromInt(1)},
		},
		Discount:      decimal.NewFromInt(1),
		CreditsEnable: true,
		CreditsOnly:   true,
	})
	assert.NoError(err)
}

func TestTenantOpenAPISuite(t *testing.T) {
	suite.Run(t, new(OpenAPITestSuite))
}

func (suite *OpenAPITestSuite) TestRedirect() {
	assert := suite.Assert()
	datainit.CreateBillingConfig(1, entity.BillingConfigType_MSP)
	billingConfigID, err := (&billingconfig.BillingConfigModel{}).GetActiveBillingConfigID(1)
	assert.NoError(err)
	info, err := creditsPackageModel.CreateCreditsPackage(1, &forms.CreditsPackage{
		StartDate:             datainit.BillingDate.AddDate(0, 0, 1),
		ExpiredDate:           datainit.BillingDate.AddDate(0, 1, 0),
		TotalCredits:          decimal.NewFromInt(100),
		Usage:                 entity.CreditsPackageUsage_POC,
		UnitFilters:           []*forms.UnitFilterSlim{{FilterID: config.Get().GetUint(config.GeneralCreditTypeID)}},
		BindedBillingConfigID: &billingConfigID,
	})
	assert.NoError(err)
	w := tests.PerformRequestWithOpenAPIHeader(suite.router, "GET", "/v1beta1/msp/credits", nil)
	assert.Equal(http.StatusOK, w.Code)
	fmt.Println(w.Body.String())
	var credits []forms.MspCredit
	err = json.NewDecoder(w.Body).Decode(&credits)
	assert.NoError(err)
	assert.Len(credits, 1)
	assert.Equal(info.TotalCredits, credits[0].Credit)
}
