package common

import (
	"errors"

	"gorm.io/gorm"

	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/infra/repoimpl/schema"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
)

func SaveWithVersioning(wdb *gorm.DB, value any, omits []string) bizerr.BizError {
	dst, ok := value.(schema.IdAndVersioning)
	if !ok {
		return bizerr.WrapGormError(wdb.Save(value).Error, "save to db")
	}

	id := dst.GetId()
	versioning := dst.GetVersioning()

	var ver schema.Versioned
	if err := wdb.Unscoped().Model(value).Select("versioning").Where("id=?", id).Take(&ver).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return bizerr.WrapGormError(wdb.Create(value).Error, "create to db")
		}
		return bizerr.WrapGormError(err, "find version")
	}

	wdb = wdb.Unscoped().Model(value).Select("*").Where("id=? AND versioning=?", id, versioning)
	if len(omits) > 0 {
		wdb = wdb.Omit(omits...)
	}
	result := wdb.Updates(value)
	if err := result.Error; err != nil {
		return bizerr.WrapGormError(err, "update to db")
	}
	if result.RowsAffected == 0 {
		return bizerr.New(bizerr.ErrCodeOptimisticLockConflict, "version conflict,current=%d", versioning)
	}
	return nil
}
