package models

import (
	"context"
	"fmt"
	jsoniter "github.com/json-iterator/go"
	mhayaTime "github.com/mhaya/extend/time"
	"github.com/mhaya/game/game_cluster/internal/constant"
	"github.com/mhaya/game/game_cluster/internal/data"
	"github.com/mhaya/game/game_cluster/internal/mdb"
	"github.com/mhaya/game/game_cluster/internal/param"
	"github.com/mhaya/game/game_cluster/internal/third"
	mhayaLogger "github.com/mhaya/logger"
	"time"
)

type RankBase struct {
	ID        int               `json:"id" bson:"id"`
	Rank      int               `json:"rank" bson:"rank"`
	score     int               `json:"score" bson:"score"`
	Status    int               `json:"status" bson:"status"` //0无奖励1未领取2已领取
	ClaimTime int64             `json:"claimTime" bson:"claimTime"`
	Reward    []data.ItemReward `json:"reward" bson:"reward"`
}

type RankReward map[int]*RankBase

func NewRankReward() map[int]*RankBase {
	return make(map[int]*RankBase)
}

func (r RankReward) InitRank(uid string, tp int) {
	ret := data.RankConfig.GetAll()
	for _, v := range ret {
		if v.Type == tp {
			ID := v.ID
			key := GetRankKey(ID, 1, false)
			rank := GetPlayerRank(key, uid)
			score := GetPlayerRankScore(key, uid)
			r[ID] = &RankBase{
				ID:        ID,
				Rank:      rank,
				score:     score,
				Status:    0,
				ClaimTime: 0,
				Reward:    data.RankRewardConfig.GetRewardByRank(v.ID, rank),
			}
			if len(r[ID].Reward) > 0 {
				r[ID].Status = 1
			}
		}
	}
}

func GetPlayBaseKey(uid string) string {
	return fmt.Sprintf("%v:%v", constant.PlayerBaseKey, uid)
}

func GetRankKey(id, tp int, yesterday bool) string {
	ret, ok := data.RankConfig.Get(id)
	if !ok {
		return ""
	}
	key := fmt.Sprintf("%s", constant.RankKey)
	if ret.StartTime != "" && ret.EndTime != "" {
		stime, err := time.Parse(ret.StartTime, mhayaTime.DateTimeFormat)
		if err != nil {
			return ""
		}
		sTime := mhayaTime.CreateFromTimestamp(stime.Unix())
		if sTime.After(time.Now()) {
			return ""
		}

		etime, err := time.Parse(ret.EndTime, mhayaTime.DateTimeFormat)
		if err != nil {
			return ""
		}

		eTime := mhayaTime.CreateFromTimestamp(etime.Unix())
		if eTime.Before(time.Now()) {
			return ""
		}
	}
	switch ret.Type {
	case 1:
		if tp == 0 {
			key = fmt.Sprintf("%s:%v:%v", key, id, mhayaTime.Now().Format(mhayaTime.DateFormat))
		} else {
			if yesterday {
				key = fmt.Sprintf("%s:%v:%v", key, id, mhayaTime.Now().Add(-24*time.Hour).Format(mhayaTime.DateFormat))
			} else {
				key = fmt.Sprintf("%s:%v:%v", key, id, mhayaTime.Now().Format(mhayaTime.DateFormat))
			}
		}
		/*		//临时修改为小时榜
				if tp == 0 {
					key = fmt.Sprintf("%s:%v:%v", key, id, mhayaTime.CreateFromTime(mhayaTime.Now().Hour(), 0, 0).ToDateTimeFormat())
				} else {
					key = fmt.Sprintf("%s:%v:%v", key, id, mhayaTime.CreateFromTime(mhayaTime.Now().Add(-1*time.Hour).Hour(), 0, 0).ToDateTimeFormat())
				}*/

	case 2:
		if tp == 0 {
			key = fmt.Sprintf("%s:%v:%v", key, id, mhayaTime.Now().StartOfWeek().Format(mhayaTime.DateFormat))
		} else {
			key = fmt.Sprintf("%s:%v:%v", key, id, mhayaTime.Now().StartOfWeek().Add(-7*24*time.Hour).Format(mhayaTime.DateFormat))
		}
	}

	return key
}

func SetRank(source, isRobot int, uid string, score int) error {
	ret := data.RankConfig.GetAll()
	ctx := context.Background()
	i := float64(2*1e12-time.Now().UnixMilli()) / 1e13
	for _, v := range ret {
		if v.Source == source {
			if v.IsBot == 0 && isRobot == 1 {
				continue
			}
			key := GetRankKey(v.ID, 0, false)
			err := mdb.RDB.ZIncrBy(ctx, key, float64(score)+i, uid).Err()
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func GetPlayerRank(key, uid string) int {
	ctx := context.Background()
	rank, err := mdb.RDB.ZRevRank(ctx, key, uid).Result()
	if err != nil {
		return -1
	}
	return int(rank) + 1
}

func GetCountryRank(key, uid string) int {
	ctx := context.Background()
	rank, err := mdb.RDB.ZRevRank(ctx, key, uid).Result()
	if err != nil {
		return -1
	}
	return int(rank) + 1
}

func GetCountryRankScore(key, uid string) int64 {
	ctx := context.Background()
	score, err := mdb.RDB.ZScore(ctx, key, uid).Result()
	if err != nil {
		return 0
	}
	return int64(score)
}

func GetPlayerRankScore(key, uid string) int {
	ctx := context.Background()
	score, err := mdb.RDB.ZScore(ctx, key, uid).Result()
	if err != nil {
		return 0
	}
	return int(score)
}

func GetRankList(id, tp int) map[int]*param.PlayerBase {
	ret, ok := data.RankConfig.Get(id)
	if !ok {
		return nil
	}
	ctx := context.Background()
	key := GetRankKey(id, tp, false)
	ranks, err := mdb.RDB.ZRevRangeWithScores(ctx, key, 0, int64(ret.ShowTotal)-1).Result()
	if err != nil {
		return nil
	}

	rankList := make(map[int]*param.PlayerBase)
	for k, v := range ranks {
		uid := v.Member.(string)
		info := mdb.RDB.HGet(ctx, constant.PlayerBaseKey, uid).Val()
		var playerBase param.PlayerBase
		jsoniter.Unmarshal([]byte(info), &playerBase)

		rankList[k+1] = &param.PlayerBase{
			UserName:      playerBase.UserName,
			UserNameMaybe: playerBase.UserNameMaybe,
			Avatar:        playerBase.Avatar,
			OpenId:        playerBase.OpenId,
			NickName:      playerBase.NickName,
			Rank:          k + 1,
			Score:         int(v.Score),
			Reward:        data.RankRewardConfig.GetRewardByRank(id, k+1),
		}
	}
	return rankList
}

func SetCountryRank(ip string, item *data.ItemReward) {
	country, err := third.GetCountryByIP(ip)

	countryConfig := data.ContryConfig.GetAll()
	all := data.RankConfig.GetAll()
	fmt.Println(all)
	countryMap := make(map[string]*data.ContryConfigRow, 0)
	for _, row := range countryConfig {
		countryMap[row.NameI] = row
	}

	if _, ok := countryMap[country]; !ok {
		country = "UN"
	}

	if err != nil {
		mhayaLogger.Warnf("Login SetCountryRank error:%v", err)
		return
	}

	key := fmt.Sprintf("%s", constant.CountryRankKey)
	ctx := context.Background()
	i := float64(2*1e12-time.Now().UnixMilli()) / 1e13
	score := item.Amount
	mdb.RDB.ZIncrBy(ctx, key, float64(score)+i, country)
}

func GetCountryRankList(countryMap map[string]*data.ContryConfigRow) map[int]*param.CountryBase {
	ctx := context.Background()
	key := fmt.Sprintf("%s", constant.CountryRankKey)
	ranks, err := mdb.RDB.ZRevRangeWithScores(ctx, key, 0, int64(50)-1).Result()
	if err != nil {
		return nil
	}

	rankList := make(map[int]*param.CountryBase)
	for _, value := range countryMap {
		mhayaLogger.Debugf("value", value)
	}
	for k, v := range ranks {
		uid := v.Member.(string)
		mhayaLogger.Debugf("GetCountryRankList => uid:%s", uid)
		var cName string
		var icon_flag string
		if country, ok := countryMap[uid]; ok {
			cName = country.NameII
			icon_flag = country.Icon_flag
		} else {
			cName = "UN"
			icon_flag = countryMap[cName].Icon_flag
		}
		rankList[k+1] = &param.CountryBase{
			Country: cName,
			Score:   int64(v.Score),
			Rank:    k + 1,
			Icon:    icon_flag,
		}
	}
	return rankList
}
