package main

import (
	"../mod"
	"../nt"
	pb "../protos"
	"../utils"
	"encoding/json"
	"strconv"
	"time"
)

const (
	DEF_MULTI      = 1
	DEF_MULTI_FROM = 2
)

// redis 获得用户 vip 等级
func get_user_vip(guid uint64) (int, error) {
	svip, err := mod.GetUserAttr(guid, "vip")
	if nil != err {
		return 0, err
	}
	vip, err := strconv.ParseInt(svip, 10, 32)
	if err != nil {
		return 0, err
	}
	return int(vip), nil
}

func __get_vip_checkin_multi(vip int) int64 {
	imulti, ok := nt.DynConf.Kv["vip_checkin7_multi"]
	if !ok {
		return DEF_MULTI
	}
	multi := utils.If_to_int64(imulti, 0)
	if multi <= 0 {
		return DEF_MULTI
	}

	from_level := DEF_MULTI_FROM
	ifrom, ok := nt.DynConf.Kv["vip_multi_from"]
	if ok {
		from := int(utils.If_to_int32(ifrom, 0))
		if from >= 0 || from < len(nt.DynConf.Vip) {
			from_level = from
		}
	}
	if vip >= from_level {
		return multi
	}
	return DEF_MULTI
}

// 初始化用户签到状态表
func __init_user_checkin7_status(vip int) ([]*pb.CheckinItem, error) {
	if vip < 0 || vip >= len(nt.DynConf.Checkin7) {
		return nil, utils.ErrIndexOutOfRange
	}

	var ret []*pb.CheckinItem

	for i := 0; i < 7; i++ {
		if i >= len(nt.DynConf.Checkin7[vip].Val) {
			return nil, utils.ErrIndexOutOfRange
		}

		item := pb.CheckinItem{
			Bonus: nt.DynConf.Checkin7[vip].Val[i],
			Got:   int32(pb.RewardStatus_NOTYET),
			Ts:    0,
		}
		ret = append(ret, &item)
	}
	// 初始化后，第一天可领
	ret[0].Got = int32(pb.RewardStatus_INREADY)
	return ret, nil
}

//  根据当前等级更新签到表
func __update_checkin_status(vip int, status []*pb.CheckinItem) error {
	if vip < 0 || vip > len(nt.DynConf.Checkin7) {
		return utils.ErrIndexOutOfRange
	}
	if len(status) <= 0 {
		return utils.ErrEmptySlice
	}
	for i := 0; i < len(status); i++ {
		if status[i].Got != int32(pb.RewardStatus_GOTTEN) {
			status[i].Bonus = nt.DynConf.Checkin7[vip].Val[i]
		}
	}
	return nil
}

func Checkin7GetUserStatus(guid uint64, checkin *pb.S_Checkin7) pb.ErrCode {
	vip, err := get_user_vip(guid)
	if err != nil {
		return pb.ErrCode_UNKNOWN
	}

	sstatus, err := mod.GetUserCheckinStatus(guid)
	if err != nil {
		return pb.ErrCode_FAILED
	}
	if len(sstatus) < 5 { // 未设置
		checkin.Status, err = __init_user_checkin7_status(vip)
		if err != nil {
			return pb.ErrCode_UNKNOWN
		}
		return pb.ErrCode_OK
	}
	// 解析
	err = json.Unmarshal([]byte(sstatus), &checkin.Status)
	if nil != err {
		return pb.ErrCode_UNKNOWN
	}
	// 更新为当前 vip 配置
	err = __update_checkin_status(vip, checkin.Status)
	if nil != err {
		return pb.ErrCode_FAILED
	}
	// 自然不自然
	tsn := time.Now().Unix() // 当前时间戳
	tsa := int64(0)          // 最近领取时间戳
	alldone := true          // 是否全部已领取
	first_not_done := 0      // 第一个未领取的下标
	for i, st := range checkin.Status {
		if st.Got == int32(pb.RewardStatus_GOTTEN) {
			tsa = st.Ts
		} else {
			alldone = false
			first_not_done = i
			break
		}
	}
	// 最近领取距离当前时间大于1天
	diffdays := utils.DiffDays(tsa, tsn)
	if diffdays > 1 || (alldone && diffdays >= 1) {
		// 重新初始化
		checkin.Status, err = __init_user_checkin7_status(vip)
		if nil != err {
			return pb.ErrCode_UNKNOWN
		}
		jsstatus, err := json.Marshal(checkin.Status)
		if err != nil {
			return pb.ErrCode_UNKNOWN
		}
		err = mod.UpdateCheckinStatus(guid, string(jsstatus))
		if nil != err {
			return pb.ErrCode_FAILED
		}
	} else if diffdays == 1 {
		checkin.Status[first_not_done].Got = int32(pb.RewardStatus_INREADY)
	}

	// 返回
	return pb.ErrCode_OK
}

func Checkin7GetBonus(guid uint64, day int32) (int64, int64, pb.ErrCode) {
	vip, err := get_user_vip(guid)
	if err != nil {
		return 0, 0, pb.ErrCode_UNKNOWN
	}

	sstatus, err := mod.GetUserCheckinStatus(guid)
	if err != nil {
		return 0, 0, pb.ErrCode_FAILED
	}

	var status []*pb.CheckinItem
	if len(sstatus) < 5 {
		status, err = __init_user_checkin7_status(vip)
		if err != nil {
			return 0, 0, pb.ErrCode_FAILED
		}
	} else {
		err = json.Unmarshal([]byte(sstatus), &status)
		if err != nil {
			return 0, 0, pb.ErrCode_FAILED
		}
		// 更新为当前 vip 等级
		err = __update_checkin_status(vip, status)
		if err != nil {
			return 0, 0, pb.ErrCode_FAILED
		}
	}
	// 根据参数领取
	if int(day) > len(status) {
		return 0, 0, pb.ErrCode_UNKNOWN
	}
	if status[day-1].Got == int32(pb.RewardStatus_GOTTEN) {
		return 0, 0, pb.ErrCode_DUP_OPER
	}
	if day-1 != 0 {
		// 只能挨着领取
		if status[day-2].Got != int32(pb.RewardStatus_GOTTEN) {
			return 0, 0, pb.ErrCode_FORBIDDEN
		}

		last_time := status[day-2].Ts
		now := time.Now().Unix()
		// 一天领一次
		if utils.TheSameDay(last_time, now) {
			return 0, 0, pb.ErrCode_DUP_OPER
		}
	}
	// 领取
	if status[day-1].Bonus < 0 {
		return 0, 0, pb.ErrCode_UNKNOWN
	}
	multi := __get_vip_checkin_multi(vip)
	bonus := status[day-1].Bonus * multi
	//status[day-1].Bonus = bonus

	status[day-1].Got = int32(pb.RewardStatus_GOTTEN)
	status[day-1].Ts = time.Now().Unix()

	// 保存状态
	data, err := json.Marshal(status)
	if err != nil {
		return 0, 0, pb.ErrCode_UNKNOWN
	}
	err = mod.UpdateCheckinStatus(guid, string(data))
	if nil != err {
		return 0, 0, pb.ErrCode_FAILED
	}

	newBalance, err := mod.AddUserBalance(guid, bonus)
	if err != nil {
		//log.Error()
		return 0, 0, pb.ErrCode_FAILED
	}
	return newBalance, bonus, pb.ErrCode_OK
}
