package tests

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

	"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/model/billing"
	"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 AuditLogTestSuite struct {
	tests.BillingTestSuite
	router              *gin.Engine
	GeneralUnitFilterID uint
	generalUnitFilter   *forms.UnitFilter
}

func (suite *AuditLogTestSuite) SetupTest() {
	suite.BillingTestSuite.SetupTest()
	_, err := (&billing.UnitModel{}).CreateUnit(&forms.UnitInfo{
		UnitKey: datainit.TestUnit,
	})
	assert := suite.Assert()
	assert.NoError(err)
	suite.generalUnitFilter, err = (&unit_filter.Model{}).CreateUnitFilter(&forms.UnitFilter{
		UnitFilterSlim: forms.UnitFilterSlim{Name: "General", Description: "General"},
		General:        true,
	})
	assert.NoError(err)
	suite.GeneralUnitFilterID = suite.generalUnitFilter.FilterID
	config.Get().Set(config.GeneralCreditTypeID, suite.generalUnitFilter.FilterID)
	packageInfo, 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)
	config.Get().Set(config.CreditsPricePackage, packageInfo.PackageID)
	suite.router = gin.New()
	suite.router.Use(ginutils.ErrorMiddleWare)
	tests.MockCentralHandler()
	api.InitializeCreditsRouter(ginutils.MyRoute{Route: suite.router})
	api.InitializeAuditLogRouter(ginutils.MyRoute{Route: suite.router})
}

func TestAuditLogSuite(t *testing.T) {
	suite.Run(t, new(AuditLogTestSuite))
}
func (suite *AuditLogTestSuite) TestSearchAuditLog() {
	assert := suite.Assert()
	now := time.Now()
	datainit.CreateBillingConfig(1, entity.BillingConfigType_DirectCustomer)

	w := tests.PerformRequest(suite.router, "POST", "/tenants/1/credits", &forms.CreateCreditsPackageReq{
		StartDate:    datainit.BillingDate,
		ExpiredDate:  now.Add(180 * 24 * 60 * time.Minute),
		TotalCredits: decimal.NewFromInt(100),
		Usage:        entity.CreditsPackageUsage_POC,
		UnitFilter:   []*forms.UnitFilterSlim{{FilterID: suite.GeneralUnitFilterID}},
	})
	assert.Equal(http.StatusOK, w.Code)
	w = tests.PerformRequest(suite.router, "GET", "/auditlog", nil)
	assert.Equal(http.StatusOK, w.Code)
	responseBody, err := io.ReadAll(w.Result().Body)
	assert.NoError(err)
	result := &[]forms.AuditLog{}
	err = json.Unmarshal(responseBody, result)
	assert.NoError(err)
	assert.Equal(1, len(*result))

	startDate := now.Add(-2 * 24 * time.Hour).Format("2006-01-02")
	endDate := now.Add(-24 * time.Hour).Format("2006-01-02")
	w = tests.PerformRequest(suite.router, "GET",
		fmt.Sprintf("/auditlog?start_date=%s&end_date=%s", startDate, endDate),
		nil,
	)
	assert.Equal(http.StatusOK, w.Code)
	responseBody, err = io.ReadAll(w.Result().Body)
	assert.NoError(err)
	result = &[]forms.AuditLog{}
	err = json.Unmarshal(responseBody, result)
	assert.NoError(err)
	assert.Equal(0, len(*result))

	w = tests.PerformRequest(suite.router, "GET",
		fmt.Sprintf("/auditlog?start_date=%s&end_date=%s", endDate, startDate),
		nil,
	)
	assert.Equal(http.StatusBadRequest, w.Code)
}
