package managementcommodity

import (
	"github.com/pingcap/dbaas/billing2/billing_errors"
	"github.com/pingcap/dbaas/billing2/db"
	"github.com/pingcap/dbaas/billing2/db/entity"
	"github.com/pingcap/dbaas/billing2/forms"
	"github.com/pingcap/errors"
	"gorm.io/gorm"
)

type CommoditySkuTemplateModel struct {
}

func (model *CommoditySkuTemplateModel) AddCommoditySkuTemplate(skuTemplateForm *forms.SkuTemplate) (err error) {
	err = model.validateCommoditySkuTemplateInput(skuTemplateForm)
	if err != nil {
		return err
	}
	skuTemplateEntity := &entity.SkuTemplate{
		EditionCode:   skuTemplateForm.EditionCode,
		CommodityCode: skuTemplateForm.CommodityCode,
		Template:      entity.DimensionValue(skuTemplateForm.Template),
		ModifierAndCreator: entity.ModifierAndCreator{
			Modifier: skuTemplateForm.ModifierAndCreator.Creator,
			Creator:  skuTemplateForm.ModifierAndCreator.Creator,
			Describe: skuTemplateForm.ModifierAndCreator.Describe,
		}}

	return skuTemplateEntity.Create(db.GetDB())
}
func (*CommoditySkuTemplateModel) validateCommoditySkuTemplateInput(skuTemplateForm *forms.SkuTemplate) (err error) {
	var checkEntity []entity.SkuTemplate
	err = entity.NewSkuTemplateQuerySet(db.GetDB()).EditionCodeEq(skuTemplateForm.EditionCode).All(&checkEntity)

	if err != nil {
		return err
	}
	if len(checkEntity) > 0 {

		return billing_errors.NewInvalidInputError(err)
	}
	return
}
func (model *CommoditySkuTemplateModel) AddSkuList(skuListForm []forms.SkuInfo) (err error) {
	var allEntity, checkEntity []entity.Unit
	var allUnitKey []string
	allUnitKeyMap := map[string]bool{}
	for _, sku := range skuListForm {
		uintEntity := entity.Unit{
			UnitKey:       sku.UnitKey,
			Description:   sku.Description,
			Category:      sku.Category,
			Provider:      sku.Provider,
			Region:        sku.Region,
			Price:         sku.Price,
			EditionCode:   sku.EditionCode,
			CommodityCode: sku.CommodityCode,
			MeasureUnit:   sku.MeasureUnit,
			SkuTemplateID: sku.SkuTemplateID,
		}
		allUnitKey = append(allUnitKey, sku.UnitKey)
		allUnitKeyMap[sku.UnitKey] = true
		allEntity = append(allEntity, uintEntity)
	}
	err = entity.NewUnitQuerySet(db.GetDB()).UnitKeyIn(allUnitKey...).All(&checkEntity)
	if err != nil {

		return err
	}
	if len(checkEntity) > 0 || len(allUnitKeyMap) != len(allUnitKey) {

		return billing_errors.NewInvalidInputError(err)
	}

	err = db.GetDB().Create(&allEntity).Error
	if err != nil {

		return err
	}
	return nil
}

func (model *CommoditySkuTemplateModel) QueryCommoditySkuTemplate(skuTemplateQuery *forms.SkuTemplateQuery) (allSkuTemplateForms []forms.SkuTemplate, err error) {
	var allEntity []entity.SkuTemplate
	query := entity.NewSkuTemplateQuerySet(db.GetDB())

	{
		if len(skuTemplateQuery.CommodityCode) > 0 {
			query = query.CommodityCodeEq(skuTemplateQuery.CommodityCode)
		}
		if len(skuTemplateQuery.EditionCode) > 0 {
			query = query.EditionCodeEq(skuTemplateQuery.EditionCode)
		}

	}

	err = query.All(&allEntity)
	if err != nil {
		return nil, err
	}
	for _, skuEntity := range allEntity {
		allSkuTemplateForms = append(allSkuTemplateForms, *skuTemplateFromEntity(&skuEntity))
	}
	return

}

func skuTemplateFromEntity(skuEntity *entity.SkuTemplate) *forms.SkuTemplate {
	return &forms.SkuTemplate{
		ID:            skuEntity.ID,
		CreatedAt:     skuEntity.CreatedAt,
		UpdatedAt:     skuEntity.UpdatedAt,
		EditionCode:   skuEntity.EditionCode,
		CommodityCode: skuEntity.CommodityCode,
		Template:      forms.DimensionValue(skuEntity.Template),
		ModifierAndCreator: forms.ModifierAndCreator{
			Modifier: skuEntity.Modifier,
			Creator:  skuEntity.Creator,
			Describe: skuEntity.Describe,
		},
	}

}

func (model *CommoditySkuTemplateModel) ModifyCommoditySkuTemplate(skuTemplateModifyForm *forms.SkuTemplateModify) (skuTemplateForms *forms.SkuTemplate, err error) {
	var skuTemplate entity.SkuTemplate
	err = db.GetDB().First(&skuTemplate, skuTemplateModifyForm.ModifyID).Error
	if err != nil {
		return nil, err
	}
	if len(skuTemplateModifyForm.SkuTemplate.Template) > 0 {
		err = db.GetDB().Model(skuTemplate).Update("template", entity.DimensionValue(skuTemplateModifyForm.SkuTemplate.Template)).Error
		if err != nil {
			return nil, err
		}
	}
	err = db.GetDB().First(&skuTemplate, skuTemplateModifyForm.ModifyID).Error
	if err != nil {
		return nil, err
	}

	return skuTemplateFromEntity(&skuTemplate), nil

}

func (model *CommoditySkuTemplateModel) QuerySkuList(form forms.SkuInfoQuery) (allSkuForm []forms.SkuInfo, err error) {
	var allEntity []entity.Unit
	query := entity.NewUnitQuerySet(db.GetDB())

	{
		if len(form.CommodityCode) > 0 {
			query = query.CommodityCodeEq(form.CommodityCode)
		}
		if len(form.EditionCode) > 0 {
			query = query.EditionCodeEq(form.EditionCode)
		}
		if len(form.UnitKey) > 0 {
			query = query.UnitKeyEq(form.UnitKey)
		}
		if form.SkuTemplateID > 0 {
			query = query.SkuTemplateIDEq(form.SkuTemplateID)

		}
	}
	err = query.All(&allEntity)
	if err != nil {
		return nil, err
	}
	for _, unitEntity := range allEntity {
		allSkuForm = append(allSkuForm, *unitFromEntity(&unitEntity))
	}
	return allSkuForm, nil

}

func unitFromEntity(e *entity.Unit) *forms.SkuInfo {
	return &forms.SkuInfo{
		UnitKey:       e.UnitKey,
		Description:   e.Description,
		Category:      e.Category,
		Provider:      e.Provider,
		Region:        e.Region,
		Price:         e.Price,
		EditionCode:   e.EditionCode,
		CommodityCode: e.CommodityCode,
		MeasureUnit:   e.MeasureUnit,
		SkuTemplateID: e.SkuTemplateID,
		ModifierAndCreator: forms.ModifierAndCreator{
			Modifier: e.Modifier,
			Creator:  e.Creator,
			Describe: e.Describe,
		},
	}

}
func (model *CommoditySkuTemplateModel) ModifyCommoditySkuInfo(skuModifyForm forms.SkuModify) (allSkuForms []forms.SkuInfo, err error) {
	var allUnitEntity []entity.Unit
	var allUnitKey []string
	for _, form := range skuModifyForm.ModifyMap {
		allUnitKey = append(allUnitKey, form.UnitKey)
	}
	err = entity.NewUnitQuerySet(db.GetDB()).UnitKeyIn(allUnitKey...).All(&allUnitEntity)
	if err != nil {
		return nil, err
	}
	if len(allUnitEntity) != len(allUnitKey) {
		return nil, billing_errors.NewInvalidInputError(errors.New("uintkey error"))
	}
	err = db.GetDB().Transaction(func(tx *gorm.DB) error {

		for _, unitEntity := range allUnitEntity {
			unitInfo := skuModifyForm.ModifyMap[unitEntity.UnitKey]
			if len(unitInfo.Description) > 0 {
				unitEntity.Description = unitInfo.Description
			}
			if len(unitInfo.Category) > 0 {
				unitEntity.Category = unitInfo.Category

			}
			if len(unitInfo.Provider) > 0 {
				unitEntity.Provider = unitInfo.Provider

			}
			if len(unitInfo.Region) > 0 {
				unitEntity.Region = unitInfo.Provider

			}
			// bug  cant modify 0

			if !unitInfo.Price.IsZero() {
				unitEntity.Price = unitInfo.Price

			}
			if len(unitInfo.MeasureUnit) > 0 {
				unitEntity.MeasureUnit = unitInfo.MeasureUnit

			}
			versionSku := entity.VersionSku{
				VersionId: unitEntity.Version,
				SkuKey:    unitEntity.UnitKey,
				Unit:      unitEntity,
			}
			unitEntity.Modifier = unitInfo.ModifierAndCreator.Modifier
			unitEntity.Description = unitInfo.ModifierAndCreator.Describe

			err = unitEntity.Update(tx, entity.UnitDBSchema.Description, entity.UnitDBSchema.Category, entity.UnitDBSchema.Provider, entity.UnitDBSchema.Region, entity.UnitDBSchema.Price, entity.UnitDBSchema.MeasureUnit)
			if err != nil {
				return err
			}
			err = versionSku.Create(tx)
			if err != nil {
				return err
			}
		}

		return nil
	})
	err = entity.NewUnitQuerySet(db.GetDB()).UnitKeyIn(allUnitKey...).All(&allUnitEntity)
	for _, unitEntity := range allUnitEntity {
		allSkuForms = append(allSkuForms, *unitFromEntity(&unitEntity))
	}
	return allSkuForms, nil

}
