package user_m

import (
	"git.hilo.cn/hilo-common/domain"
	"git.hilo.cn/hilo-common/resource/mysql"
	"gorm.io/gorm"
	"hilo-group/_const/enum/property_e"
	"hilo-group/myerr"
	"hilo-group/myerr/bizerr"
	"time"
)

//用户道具
type UserProperty struct {
	mysql.Entity
	*domain.Model `gorm:"-"`
	UserId        mysql.ID
	PropertyId    mysql.ID
	EndTime       time.Time
	Using         property_e.UserPropertyUsing
}

func GetUserPropertyOrInit(model *domain.Model, userId mysql.ID, propertyId mysql.ID) (*UserProperty, error) {
	userProperty := UserProperty{}
	if err := model.Db.Model(&UserProperty{}).Where(&UserProperty{
		UserId:     userId,
		PropertyId: propertyId,
	}).First(&userProperty).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return &UserProperty{
				Model:      model,
				UserId:     userId,
				PropertyId: propertyId,
				EndTime:    time.Now(),
			}, nil
		} else {
			return nil, myerr.WrapErr(err)
		}
	}
	userProperty.Model = model
	return &userProperty, nil
}

func GetUserPropertyOrErr(model *domain.Model, userId mysql.ID, propertyId mysql.ID) (*UserProperty, error) {
	userProperty := UserProperty{}
	if err := model.Db.Model(&UserProperty{}).Where(&UserProperty{
		UserId:     userId,
		PropertyId: propertyId,
	}).First(&userProperty).Error; err != nil {
		return nil, myerr.WrapErr(err)
	}
	userProperty.Model = model
	return &userProperty, nil
}

//获取正在使用的座驾,不存在则位nil
/*func GetUserPropertyWithUsingNil(model *domain.Model, userId mysql.ID) (*UserProperty, error) {
	userProperty := UserProperty{}
	if err := model.Db.Model(&UserProperty{}).Where(&UserProperty{
		UserId: userId,
		Using:  property_m.YesUsing,
	}).First(&userProperty).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		} else {
			return nil, myerr.WrapErr(err)
		}
	}
	userProperty.Model = model
	return &userProperty, nil
}*/

//设置为使用中
func (userProperty *UserProperty) SetUsing() (*UserProperty, error) {
	if err := ResetAllUserPropertyNoUsing(userProperty.Model, userProperty.UserId); err != nil {
		return nil, err
	}
	userProperty.Using = property_e.YesUsing
	return userProperty, nil
}

//增加结束时间
func (userProperty *UserProperty) AddEndTime(t property_e.UserPropertyLogOrginType, second uint32, operateUserId mysql.ID) (*UserProperty, mysql.ID, error) {
	logId, err := addUserPropertyLog(userProperty.Model, userProperty.UserId, userProperty.PropertyId, t, property_e.AddSecond, &second, nil, operateUserId)
	if err != nil {
		return nil, 0, myerr.WrapErr(err)
	}
	//if err := ResetAllUserPropertyNoUsing(userProperty.Model, userProperty.UserId); err != nil {
	//	return nil, logId, err
	//}
	nowTime := time.Now()
	if userProperty.EndTime.After(nowTime) {
		nowTime = userProperty.EndTime
	}
	userProperty.EndTime = nowTime.Add(time.Duration(second) * time.Second)
	return userProperty, logId, nil
}

//赠送
func (userProperty *UserProperty) Give(receiveUserId mysql.ID) (*UserProperty, *UserProperty, uint32, error) {
	remainSecond := userProperty.EndTime.Unix() - time.Now().Unix()
	if remainSecond <= 0 {
		return nil, nil, 0, bizerr.UserPropertyHasEnd
	}
	receiveUserProperty, err := GetUserPropertyOrInit(userProperty.Model, receiveUserId, userProperty.PropertyId)
	if err != nil {
		return nil, nil, 0, err
	}

	receiveUserProperty, _ , err = receiveUserProperty.AddEndTime(property_e.Give, uint32(remainSecond), userProperty.UserId)
	if err != nil {
		return nil, nil, 0, err
	}

	_, err = addUserPropertyLog(userProperty.Model, userProperty.UserId, userProperty.PropertyId, property_e.Give, property_e.Del, nil, nil, userProperty.UserId)
	if err != nil {
		return nil, nil, 0, err
	}
	userProperty.SetDel()
	return userProperty, receiveUserProperty, uint32(remainSecond), nil
}

//重置所有的座驾均为不使用状态
func ResetAllUserPropertyNoUsing(model *domain.Model, userId mysql.ID) error {
	if err := model.Db.Model(&UserProperty{}).Where(&UserProperty{
		UserId: userId,
	}).UpdateColumn("using", property_e.NoUsing).Error; err != nil {
		return myerr.WrapErr(err)
	}
	return nil
}

//增加修改日志
func addUserPropertyLog(model *domain.Model, userId mysql.ID, propertyId mysql.ID, originType property_e.UserPropertyLogOrginType, t property_e.UserPropertyLogType, addSecond *uint32, UpdateEndTime *time.Time, operateUserId mysql.ID) (mysql.ID, error) {
	userPropertyLog := UserPropertyLog{
		UserId:        userId,
		OperateUserId: operateUserId,
		PropertyId:    propertyId,
		OriginType:    originType,
		Type:          t,
		AddSecond:     addSecond,
		UpdateEndTime: UpdateEndTime,
	}
	if err := model.Db.Create(&userPropertyLog).Error; err != nil {
		return 0, myerr.WrapErr(err)
	}
	return userPropertyLog.ID, nil
}

func RemoveUserProperty(model *domain.Model, userId mysql.ID, propertyId mysql.ID) error {
	return model.Db.Where("user_id = ? AND property_id = ?", userId, propertyId).Delete(&UserProperty{}).Error
}

func (up *UserProperty) BatchGet(db *gorm.DB, userIds []uint64) (map[uint64]uint64, error) {
	rows := make([]UserProperty, 0)
	if err := db.Model(up).
		Where("end_time > NOW() AND user_id IN ?", userIds).Order("id DESC").Find(&rows).Error; err != nil {
		return nil, err
	}
	result := make(map[uint64]uint64, 0)
	tmp := make(map[uint64]uint64, 0)
	for _, i := range rows {
		if _, ok := result[i.UserId]; !ok {
			if i.Using == property_e.YesUsing {
				// using = true且id最大,就确定是当前使用的
				result[i.UserId] = i.PropertyId
			} else if _, ok := tmp[i.UserId]; !ok {
				// using = false且id最大,先记下,因为不知道还有没有using=true的
				tmp[i.UserId] = i.PropertyId
			}
		}
	}
	for k, v := range tmp {
		// result中没有的,就采用tmp保存的
		if _, ok := result[k]; !ok {
			result[k] = v
		}
	}
	return result, nil
}

//用户道具日志
type UserPropertyLog struct {
	mysql.Entity
	*domain.Model `gorm:"-"`
	UserId        mysql.ID
	OperateUserId mysql.ID
	PropertyId    mysql.ID
	OriginType    property_e.UserPropertyLogOrginType
	Type          property_e.UserPropertyLogType
	AddSecond     *mysql.Num
	UpdateEndTime *time.Time
}