package headwear_cv

import (
	"git.hilo.cn/hilo-common/resource/mysql"
	"gorm.io/gorm"
	"hilo-group/_const/enum/headwear_e"
	"hilo-group/domain/model/res_m"
	"hilo-group/domain/model/user_m"
	"hilo-group/myerr"
	"strconv"
	"time"
)

type CvHeadwear struct {
	Id        uint64    `json:"id"`
	Using     bool      `json:"using"`
	PicUrl    mysql.Str `json:"picUrl"`
	EffectUrl mysql.Str `json:"effectUrl"`
	TimeLeft  int64     `json:"timeLeft"`	// 离到期还有多少秒(过期则是负数)
}

type CvHeadwearDiamond struct {
	Id         uint64 `json:"id"`
	PicUrl     string `json:"picUrl"`
	EffectUrl  string `json:"effectUrl"`
	DiamondNum uint32 `json:"diamondNum"`
	Second     uint32 `json:"second"`
	Days       string `json:"days"`
}

func GetCvHeadwearDiamond(pageSize int, pageIndex int) ([]CvHeadwearDiamond, error) {
	headwearDiamonds := []CvHeadwearDiamond{}
	if err := mysql.Db.Raw("SELECT d.id, r.pic_url, r.effect_url, d.`second`, d.diamond_num from res_headwear r, res_headwear_diamond d where r.id = d.res_headwear_id and d.`status` = ? ORDER BY d.diamond_num asc LIMIT ?, ?", mysql.USER, (pageIndex-1)*pageSize, pageSize).Scan(&headwearDiamonds).Error; err != nil {
		return nil, myerr.WrapErr(err)
	}
	for i, _ := range headwearDiamonds {
		headwearDiamonds[i].Days = strconv.FormatUint(uint64(headwearDiamonds[i].Second/(24*60*60)), 10)
	}
	return headwearDiamonds, nil
}

func GetHeadwearList(db *gorm.DB, userId uint64) ([]CvHeadwear, error) {
	rows := make([]user_m.UserHeadwear, 0)
	if err := db.Where(&user_m.UserHeadwear{
		UserId: userId,
	}).Where("end_time >= ?", time.Now()).Order("`using` DESC, updated_time DESC").Find(&rows).Error; err != nil {
		return nil, err
	}
	resHwMap, err := res_m.GetResHeadwearMap(db)
	if err != nil {
		return nil, myerr.WrapErr(err)
	}

	result := make([]CvHeadwear, 0)
	now := time.Now()
	hasUsing := false
	for _, i := range rows {
		//  TODO: 没过期并且有设置using的,才算是,因为写入方不维护using状态的更新
		isUsing := i.Using == headwear_e.YesUsing && i.EndTime.After(now)
		result = append(result, CvHeadwear{
			Id:        i.HeadwearId,
			PicUrl:    resHwMap[i.HeadwearId].PicUrl,
			EffectUrl: resHwMap[i.HeadwearId].EffectUrl,
			Using:     isUsing,
			TimeLeft:  i.EndTime.Unix() - now.Unix(),
		})
		if isUsing {
			hasUsing = true
		}
	}
	// 如果没有一个using,则找第一个没过期的充当
	if ! hasUsing {
		for i, e := range result {
			if e.TimeLeft > 0 {
				result[i].Using = true
				break
			}
		}
	}

	return result, nil
}

func GetCvHeadwear(userId uint64) (*CvHeadwear, error) {
	userHeadwear := user_m.UserHeadwear{}
	if err := mysql.Db.Model(&user_m.UserHeadwear{}).Where(&user_m.UserHeadwear{
		UserId: userId,
	}).Where("end_time >= ?", time.Now()).Order("`using` DESC, updated_time DESC").First(&userHeadwear).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		} else {
			return nil, myerr.WrapErr(err)
		}
	}
	resHeadwear := res_m.ResHeadwear{}
	if err := mysql.Db.Model(&res_m.ResHeadwear{}).First(&resHeadwear, userHeadwear.HeadwearId).Error; err != nil {
		return nil, myerr.WrapErr(err)
	}
	return &CvHeadwear{
		Id:        userHeadwear.HeadwearId,
		PicUrl:    resHeadwear.PicUrl,
		EffectUrl: resHeadwear.EffectUrl,
		Using:     userHeadwear.Using == headwear_e.YesUsing,
	}, nil
}

func BatchGetCvHeadwears(userIds []uint64) (map[uint64]CvHeadwear, error) {
	if len(userIds) == 0 {
		return map[uint64]CvHeadwear{}, nil
	}
	rows := make([]user_m.UserHeadwear, 0)
	//asc 进行覆盖,保证了updated_time 最大的是最后的输出
	if err := mysql.Db.Where("user_id IN ?", userIds).Where("end_time >= ?", time.Now()).
		Order("`using` ASC, updated_time ASC").Find(&rows).Error; err != nil {
		return nil, err
	}
	//
	resHeadwearIds := make([]uint64, 0, len(rows))
	for i, _ := range rows {
		resHeadwearIds = append(resHeadwearIds, rows[i].HeadwearId)
	}
	//获取头饰资源,然后转换成map结构
	resHeadwearMap := map[uint64]res_m.ResHeadwear{}
	resHeadwears := []res_m.ResHeadwear{}
	if err := mysql.Db.Where("id IN ?", resHeadwearIds).Find(&resHeadwears).Error; err != nil {
		return nil, err
	}
	for i, _ := range resHeadwears {
		resHeadwearMap[resHeadwears[i].ID] = resHeadwears[i]
	}

	result := make(map[uint64]CvHeadwear, 0)
	for _, r := range rows {
		headwear, flag := resHeadwearMap[r.HeadwearId]
		if flag {
			result[r.UserId] = CvHeadwear{
				Id:        headwear.ID,
				PicUrl:    headwear.PicUrl,
				EffectUrl: headwear.EffectUrl,
				Using:     r.Using == headwear_e.YesUsing,
			}
		}

	}
	return result, nil

}