package tests

import (
	"testing"

	"github.com/pingcap/dbaas/billing2/billing_errors"
	"github.com/pingcap/dbaas/billing2/forms"
	"github.com/pingcap/dbaas/billing2/model/billing"
	"github.com/pingcap/dbaas/billing2/utils/tests"
	"github.com/stretchr/testify/suite"
)

var unitModel = &billing.UnitModel{}

type UnitTestSuite struct {
	tests.BillingTestSuite
}

func (suite *UnitTestSuite) TestCreateUnit() {
	assert := suite.Assert()
	unit := &forms.UnitInfo{
		UnitKey:     "TestKey",
		Description: "desc",
		Category:    "cate",
	}
	info, err := unitModel.CreateUnit(unit)
	assert.Nil(err)
	assert.Equal(info.UnitKey, "TestKey")
	assert.Equal(info.Description, "desc")
	assert.Equal(info.Category, "cate")
	info, err = unitModel.GetUnit("TestKey")
	assert.Nil(err)
	assert.Equal(info.UnitKey, "TestKey")
	assert.Equal(info.Description, "desc")
	assert.Equal(info.Category, "cate")
}

func (suite *UnitTestSuite) TestCreateAndUpdateUnit() {
	assert := suite.Assert()
	unit := &forms.UnitInfo{
		UnitKey:     "TestKey",
		Description: "desc",
		Category:    "cate",
	}
	info, err := unitModel.CreateUnit(unit)
	assert.NoError(err)
	assert.Equal(info.UnitKey, "TestKey")
	assert.Equal(info.Description, "desc")
	assert.Equal(info.Category, "cate")
	unit.Category = "cate1"
	info, err = unitModel.CreateAndUpdateUnit(unit)
	assert.Nil(err)
	assert.Equal(info.UnitKey, "TestKey")
	assert.Equal(info.Description, "desc")
	assert.Equal(info.Category, "cate1")
}

func (suite *UnitTestSuite) TestDeleteUnit() {
	assert := suite.Assert()
	unit := &forms.UnitInfo{
		UnitKey: "TestKey",
	}
	_, err := unitModel.CreateUnit(unit)
	assert.Nil(err)

	err = unitModel.DeleteUnit("TestKey")
	assert.Nil(err)
}

func (suite *UnitTestSuite) TestDeleteAndCreateUnit() {
	assert := suite.Assert()
	unit := &forms.UnitInfo{
		UnitKey: "TestKey",
	}
	_, err := unitModel.CreateUnit(unit)
	assert.Nil(err)

	err = unitModel.DeleteUnit("TestKey")
	assert.Nil(err)

	_, err = unitModel.CreateUnit(unit)
	assert.Nil(err)
}

func (suite *UnitTestSuite) TestUpdateUnit() {
	assert := suite.Assert()
	unit := &forms.UnitInfo{
		UnitKey:     "TestKey",
		Description: "TestDescription",
		Category:    "cate",
	}
	_, err := unitModel.CreateUnit(unit)
	assert.Nil(err)

	unit1 := &forms.UnitInfo{
		UnitKey: "TestKey",
	}

	_, err = unitModel.UpdateUnit(unit1)
	assert.Nil(err)

	resp, err := unitModel.GetUnit(unit.UnitKey)
	assert.Nil(err)
	assert.NotEqual(resp.Description, unit.Description)
	assert.Equal(resp.Description, unit1.Description)
	assert.Equal(resp.Category, unit1.Category)
}

func (suite *UnitTestSuite) TestUpdateUnitNotExist() {
	assert := suite.Assert()
	unit := &forms.UnitInfo{
		UnitKey: "TestKey",
	}
	_, err := unitModel.UpdateUnit(unit)
	assert.Error(err)
	assert.ErrorIs(err, billing_errors.ObjectNotExistsError)

	unit = &forms.UnitInfo{}
	_, err = unitModel.UpdateUnit(unit)
	assert.Error(err)
	assert.ErrorIs(err, billing_errors.ObjectNotExistsError)
}

func (suite *UnitTestSuite) TestGetAllUnits() {
	assert := suite.Assert()
	res, err := unitModel.GetAllUnits()

	assert.Nil(err)
	assert.Empty(res)

	unit := &forms.UnitInfo{
		UnitKey: "TestKey",
	}
	_, err = unitModel.CreateUnit(unit)
	assert.Nil(err)

	res, err = unitModel.GetAllUnits()
	assert.Nil(err)
	assert.Equal(len(res), 1)
	assert.Equal(res[0].UnitKey, unit.UnitKey)

	unit1 := &forms.UnitInfo{
		UnitKey: "TestKey1",
	}
	_, err = unitModel.CreateUnit(unit1)
	assert.Nil(err)

	res, err = unitModel.GetAllUnits()
	assert.Nil(err)
	assert.Equal(len(res), 2)
}
func TestUnitSuite(t *testing.T) {
	suite.Run(t, new(UnitTestSuite))
}
