package cross

import (
	"encoding/json"
	"time"

	"../log"
	"../mod"
	"../nt"
	pb "../protos"
	"../utils"
	"go.uber.org/zap"
)

type UserTurntable struct {
	Ts       int64   // 抽奖时间
	Times    int32   // 已抽次数
	Recharge int64   // 当日充值
	Blocked  []int64 // 抽中后不发，等待客户端请求, 如果玩家掉线，清除
}

// 初始化幸运转盘对象
func NewUserTurntable() *UserTurntable {
	ut := &UserTurntable{
		Ts: time.Now().Unix(),
	}
	return ut
}

func (self *UserTurntable) Reset() {
	self.Ts = time.Now().Unix()
	self.Times = 0
	self.Recharge = 0
}

// 得到用户当前转盘状态
// 正常从 redis 解析；否则重新生成
// 解析出来 Ts 不是当天，则立即充值所有信息
func _getUserTurntable(guid uint64) *UserTurntable {
	ut := NewUserTurntable()

	s, err := mod.GetTurntable(guid)
	if err != nil || len(s) <= 0 {
		return ut
	}

	rut := NewUserTurntable()
	err = json.Unmarshal([]byte(s), rut)
	if nil != err {
		return ut
	}
	now := time.Now().Unix()
	if !utils.TheSameDay(now, rut.Ts) {
		return ut
	}

	return rut
}

// 保存结构
func _setUserTurntable(guid uint64, c *UserTurntable) error {
	bytes, err := json.Marshal(c)
	if err != nil {
		log.Error("_setUserTurntable", zap.Uint64("guid", guid), zap.Error(err))
		return err
	}

	return mod.UpdateTurntable(guid, string(bytes))
}

// 根据规则获得总的可转盘次数
func _getUserTotalTimes(guid uint64, c *UserTurntable) (int32, error) {
	// 总次数
	svip, err := mod.GetUserAttr(guid, "vip")
	if nil != err {
		return 0, err
	}
	vip64, err := utils.StrToInt64(svip)
	if err != nil {
		return 0, err
	}
	totalTimes := int32(vip64)
	totalTimes += int32(c.Recharge / 10000)

	return totalTimes, nil
}

// 某个用户状态
func TurntableStatus(guid uint64) *pb.S_TurnTableStatus {
	r := &pb.S_TurnTableStatus{
		Ec:         0,
		Recharge:   0,
		TotalTimes: 0,
		Times:      0,
	}

	// 总次数
	userConf := _getUserTurntable(guid)
	total, err := _getUserTotalTimes(guid, userConf)
	if err != nil {
		log.Error("TurntableStatus", zap.Uint64("guid", guid), zap.Error(err))
		r.Ec = int32(pb.ErrCode_FAILED)
		return r
	}
	r.TotalTimes = total

	remain := r.TotalTimes - userConf.Times
	if remain < 0 {
		remain = 0
	}
	// 当前剩余次数
	r.Times = remain
	r.Recharge = userConf.Recharge

	// 转盘配置
	r.Turntable = nt.DynConf.Turntable.GetRewards()

	return r
}

// 充值回调
func TurntableOnUserRecharge(guid uint64, delta int64) error {
	userConf := _getUserTurntable(guid)
	userConf.Recharge += delta

	return _setUserTurntable(guid, userConf)
}

// 离线清除 Block
func TurntableClearBlocked(guid uint64) error {
	userConf := _getUserTurntable(guid)

	if len(userConf.Blocked) > 0 {
		userConf.Blocked = []int64{}
		return _setUserTurntable(guid, userConf)
	}

	return nil
}

// 玩一次
func TurntablePlay(guid uint64) *pb.S_TurnTablePlay {
	r := &pb.S_TurnTablePlay{
		Ec:    0,
		Index: 0,
		Times: 0,
	}
	userConf := _getUserTurntable(guid)
	//
	total, err := _getUserTotalTimes(guid, userConf)
	if err != nil {
		r.Ec = int32(pb.ErrCode_FAILED)
		return r
	}
	//
	if userConf.Times >= total {
		r.Ec = int32(pb.ErrCode_EXHANSTED)
		return r
	}
	if !IsBindUser(guid) {
		r.Ec = int32(pb.ErrCode_UNBIND)
		return r
	}

	r.Index = int32(nt.DynConf.Turntable.Choice())
	reward := nt.DynConf.Turntable.RewardProb[r.Index].Reward

	// 更新次数 : 玩了就算次数，不领奖也增加次数
	userConf.Ts = time.Now().Unix()
	userConf.Times += 1
	userConf.Blocked = append(userConf.Blocked, reward)
	remain := total - userConf.Times
	if remain < 0 {
		remain = 0
	}

	r.Times = remain

	err = _setUserTurntable(guid, userConf)
	if err != nil {
		r.Ec = int32(pb.ErrCode_FAILED)
		return r
	}

	return r
}

func TurntablePeekAll(guid uint64) ([]int64, pb.ErrCode) {
	userConf := _getUserTurntable(guid)
	if len(userConf.Blocked) <= 0 {
		return nil, pb.ErrCode_TARGET_NOT_FOUND
	}

	var ret []int64
	ret = append(ret, userConf.Blocked...)
	// 每次请求就清空
	userConf.Blocked = []int64{}

	err := _setUserTurntable(guid, userConf)
	if nil != err {
		return nil, pb.ErrCode_FAILED
	}

	return ret, pb.ErrCode_OK
}
