package costcenter

import (
	"errors"
	"fmt"
	"github.com/pingcap/dbaas/cost-metering-service/billing_errors"
	"github.com/pingcap/dbaas/cost-metering-service/db"
	"github.com/pingcap/dbaas/cost-metering-service/db/entity"
	"github.com/pingcap/dbaas/cost-metering-service/errorutils"
	"github.com/pingcap/dbaas/cost-metering-service/forms"
	"github.com/pingcap/dbaas/cost-metering-service/log"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

type CostCenterModel struct {
}

func (model *CostCenterModel) CreateAndUpdateCostCenter(costCenter *forms.CostCenter) (*forms.CostCenter, error) {
	isUpdate := false
	fromDb := &entity.CostCenter{}

	err := entity.NewCostCenterQuerySet(db.GetDB()).CostCenterNameEq(costCenter.CostCenterName).One(fromDb)
	if err != nil {
		if errors.Is(err, billing_errors.ObjectNotExistsError) {
			isUpdate = false
		} else {
			return nil, err
		}
	} else {
		isUpdate = true
	}

	inDB := &entity.CostCenter{
		CostCenterOrgID: costCenter.CostCenterOrgID,
		CostCenterName:  costCenter.CostCenterName,
		Description:     costCenter.Description,
		Status:          entity.CostCenterStatus_NOT_STARTED,
	}
	if !isUpdate {

		err = inDB.Create(db.GetDB())
		if err != nil {
			return nil, err
		}
	} else {
		err = db.GetDB().Transaction(func(tx *gorm.DB) error {
			err = db.GetDB().Model(fromDb).Where("unit_key", fromDb.CostCenterName).Updates(inDB).Error
			if err != nil {
				log.Error("CreateAndUpdateCostCenter error", zap.Any("inDB", inDB), zap.Error(err))
				return err
			}

			return nil

		})
		if err != nil {
			return nil, err
		}

	}

	return costCenterFromEntity(inDB), nil
}
func costCenterFromEntity(costCenter *entity.CostCenter) *forms.CostCenter {
	return &forms.CostCenter{
		CostCenterOrgID: costCenter.CostCenterOrgID,
		CostCenterName:  costCenter.CostCenterName,
		Description:     costCenter.Description,
	}
}

func (model *CostCenterModel) GetAllCostCenters() ([]forms.CostCenter, error) {
	var costCenterList []entity.CostCenter
	err := entity.NewCostCenterQuerySet(db.GetDB()).All(&costCenterList)
	if err != nil {
		return nil, err
	}
	var result = make([]forms.CostCenter, len(costCenterList))
	for i, costCenter := range costCenterList {
		result[i] = *costCenterFromEntity(&costCenter)
	}
	return result, nil
}

func (model *CostCenterModel) GetCostCenter(costCenterName string) (*forms.CostCenter, error) {
	result := &forms.CostCenter{}

	costCenter := &entity.CostCenter{}
	err := errorutils.WrapSQLError(entity.NewCostCenterQuerySet(db.GetDB()).CostCenterNameEq(costCenterName).One(costCenter), fmt.Sprintf("costCenter %v", costCenterName))
	if err != nil {
		return nil, err
	}
	result = costCenterFromEntity(costCenter)
	return result, nil
}
