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/forms"
	"github.com/pingcap/dbaas/billing2/model/billing"
	"github.com/pingcap/dbaas/billing2/utils/ginutils"
	"github.com/pingcap/dbaas/billing2/utils/tests"
	"github.com/stretchr/testify/suite"
)

var subscriptionModel = &billing.SubscriptionModel{}

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

func (suite *SubscriptionTestSuite) SetupTest() {
	suite.BillingTestSuite.SetupTest()
	suite.router = gin.New()
	suite.router.Use(ginutils.ErrorMiddleWare)
	tests.MockCentralHandler()
	api.InitializeSubscriptionRouter(ginutils.MyRoute{Route: suite.router})
}

func TestSubscriptionSuite(t *testing.T) {
	suite.Run(t, new(SubscriptionTestSuite))
}

func (suite *SubscriptionTestSuite) TestGetSubscription() {
	assert := suite.Assert()

	subscription := &forms.Subscription{
		FilePath:      "file_path",
		ContractEmail: "contract_email",
	}
	tenantID := uint(1)
	info, err := subscriptionModel.CreateSubscription(tenantID, subscription)
	assert.NoError(err)

	w := tests.PerformGetRequest(suite.router, fmt.Sprintf("/tenants/1/subscriptions/%d", info.SubscriptionID))
	assert.Equal(http.StatusOK, w.Code)
	response := &forms.Subscription{}
	err = json.Unmarshal(w.Body.Bytes(), response)
	assert.NoError(err)
	assert.Equal(info, response)
}

func (suite *SubscriptionTestSuite) TestCreateSubscription() {
	assert := suite.Assert()

	subscription := &forms.SubscriptionInput{
		FilePath:      "file_path",
		ContractEmail: "contract_email",
	}

	w := tests.PerformRequest(suite.router, "POST", "/tenants/1/subscriptions", subscription)
	assert.Equal(http.StatusOK, w.Code)
	response := &forms.Subscription{}
	err := json.Unmarshal(w.Body.Bytes(), response)
	assert.NoError(err)

	info, err := subscriptionModel.GetSubscription(response.SubscriptionID)
	assert.NoError(err)
	assert.Equal(info, response)
}

func (suite *SubscriptionTestSuite) TestDownloadSubscription() {
	assert := suite.Assert()

	subscription := &forms.Subscription{
		FilePath:      "abc.pdf",
		ContractEmail: "contract_email",
	}
	tenantID := uint(1)
	info, err := subscriptionModel.CreateSubscription(tenantID, subscription)
	assert.NoError(err)

	w := tests.PerformRequest(suite.router, "POST", fmt.Sprintf("/tenants/1/subscriptions/%d/actions/download", info.SubscriptionID), nil)
	assert.Equal(http.StatusOK, w.Code)
	assert.EqualValues(w.Body.String(), "mock_file_content")
	assert.EqualValues(w.Header()["Content-Type"][0], "application/octet-stream")
	assert.Regexp("attachment.*", w.Header()["Content-Disposition"][0])
}
