package tests

import (
	"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/handler/centralhandler"
	"github.com/pingcap/dbaas/billing2/utils/ginutils"
	"github.com/pingcap/dbaas/billing2/utils/tests"
	"github.com/pingcap/dbaas/billing2/utils/tests/datainit"
	"github.com/stretchr/testify/suite"
)

type MockCentralHandlerImpl struct {
	centralhandler.CentralHandler
	tenants []forms.Tenant
}

func (*MockCentralHandlerImpl) GetTenant(tenantID uint) (*forms.Tenant, error) {
	return &forms.Tenant{
		TenantID: tenantID,
		Status:   centralhandler.TenantStatusActive,
	}, nil
}
func (i *MockCentralHandlerImpl) SetAllTenants(tenants []forms.Tenant) {
	i.tenants = tenants
}

func (i *MockCentralHandlerImpl) GetAllTenants() ([]forms.Tenant, error) {
	return i.tenants, nil
}

func (i *MockCentralHandlerImpl) GetTenants(ids ...uint) ([]forms.Tenant, error) {
	return i.tenants, nil
}

func (*MockCentralHandlerImpl) DownloadFile(string) ([]byte, error) {
	return nil, nil
}

func (*MockCentralHandlerImpl) GetUser(userID uint) (*forms.User, error) {
	return &forms.User{
		UserID: userID,
	}, nil
}

func (*MockCentralHandlerImpl) GetTenantIdByOpenAPIAccess(apiKey string) (tenantID uint64, err error) {
	return 1, nil
}

func (*MockCentralHandlerImpl) GetProjectInfo(projectID uint) (*forms.Project, error) {
	return &forms.Project{
		ID:   projectID,
		Name: "project",
	}, nil
}

func mockCentral() {
	central := &MockCentralHandlerImpl{}
	central.SetAllTenants([]forms.Tenant{
		{
			TenantID: 1,
		},
	})
	centralhandler.SetCentralHandler(central)
}

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

func (suite *WorkerTestSuite) SetupTest() {
	suite.BillingTestSuite.SetupTest()
	suite.router = gin.New()
	suite.router.Use(ginutils.ErrorMiddleWare)
	api.InitializeWorkerRunActionRouter(ginutils.MyRoute{Route: suite.router})
}

func TestWorkerTestSuite(t *testing.T) {
	suite.Run(t, new(WorkerTestSuite))
}

func (suite *WorkerTestSuite) TestWorkerTaskAPI() {
	mockCentral()
	assert := suite.Assert()

	w := tests.PerformRequest(suite.router, "POST", "/worker/run", &forms.WorkerTaskAction{
		Action:  "support_plan_metering",
		RunTime: datainit.BillingDate,
	})
	assert.Equal(http.StatusOK, w.Code)

	w = tests.PerformRequest(suite.router, "POST", "/worker/run", &forms.WorkerTaskAction{
		Action:  "invalid",
		RunTime: datainit.BillingDate,
	})
	assert.Equal(http.StatusBadRequest, w.Code)

}

func (suite *WorkerTestSuite) TestWorkerSubTaskAPI() {
	assert := suite.Assert()
	w := tests.PerformRequest(suite.router, "POST", "/worker/subtask/run", &forms.WorkerSubTaskAction{
		Action:   "support_plan_metering",
		RunTime:  datainit.BillingDate,
		TenantID: 1,
	})
	assert.Equal(http.StatusOK, w.Code)

	w = tests.PerformRequest(suite.router, "POST", "/worker/subtask/run", &forms.WorkerSubTaskAction{
		Action:   "invalid",
		RunTime:  datainit.BillingDate,
		TenantID: 1,
	})
	assert.Equal(http.StatusBadRequest, w.Code)

}
