package models

import (
	"context"
	"fmt"
	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"
	clog "github.com/mhaya/logger"
	"time"
)

const (
	DailyRecordNewRegistered = iota + 1
	DailyRecordLoggedIn
	DailyRecordNewLogin
	DailyRecordOldLogin
	DailyRecordActiveUsers
	DailyRecordNewActive
	DailyRecordOldActive
	DailyRecordTotalPoints
	DailyRecordUProduced
	DailyRecordUCashout
	DailyRecordTonCashout
)

const (
	TotalUser = iota + 1
	UserLevel
)

type DailyRecord struct {
	Platform    string  `bson:"platform"  json:"platform"`        // platform: 用户所在的平台，例如“Android”或“IOS”
	Channel     string  `bson:"channel" json:"channel"`           // channel: 用户来源渠道
	Daily       int64   `bson:"daily" json:"daily"`               //日期
	Registered  int64   `bson:"registered" json:"registered"`     // registered: 新用户注册的数量
	LoggedIn    int64   `bson:"logged_in" json:"logged_in"`       // logged_in: 登陆产品的用户数量
	NewLogin    int64   `bson:"new_login" json:"new_login"`       // new_login: 登陆产品的新注册用户数量
	OldLogin    int64   `bson:"old_login" json:"old_login"`       // old_login: 登陆产品的老用户数量
	ActiveUsers int64   `bson:"active_users" json:"active_users"` // active_users: 登录游戏后投掷过骰子的用户数量
	NewActive   int64   `bson:"new_active" json:"new_active"`     // new_active: 登录游戏后投掷过骰子的新用户数量
	OldActive   int64   `bson:"old_active" json:"old_active"`     // old_active: 登录游戏后投掷过骰子的老用户数量
	TotalPoints int64   `bson:"total_points" json:"total_points"` // total_points: 全服积分产出总值
	UProduced   float64 `bson:"u_produced" json:"u_produced"`     // u_produced: 全服U的产出总值
	UCashout    float64 `bson:"u_cashout" json:"u_cashout"`       // u_cashout: 全服U的提现总值
	CreatedAt   int64   `bson:"createdAt" json:"createdAt"`       // CreatedAt: 数据记录的时间戳
	UpdatedAt   int64   `bson:"updatedAt" json:"updatedAt"`
}

func GetWeekRecordKey(userName string, itemBaseType int, itemId int) string {
	key := fmt.Sprintf("%v:%v:%v:%v", constant.WeekItemRecordKey, userName, itemBaseType, itemId)
	return key
}

// GetDailyRecordKey 当天
func GetDailyRecordKey(platform, channel string, op int) string {
	Daily := mhayaTime.Now().DailyTOTimeStamp()
	return fmt.Sprintf("%v:%v:%s:%s:%v", constant.PlayerDailyKey, Daily, platform, channel, op)
}

// GetAppointDailyRecordKey 指定时间
func GetAppointDailyRecordKey(platform, channel string, daily int64, op int) string {
	return fmt.Sprintf("%v:%v:%s:%s:%v", constant.PlayerDailyKey, daily, platform, channel, op)
}

// SetDailyRecord 设置当天指定键值数据
func SetDailyRecord(platform, channel string, op, num int) {
	key := GetDailyRecordKey(platform, channel, op)
	mdb.RDB.IncrBy(context.Background(), key, int64(num))
}

func GetAppointDailyRecord(platform, channel string, daily int64, op int) (int64, error) {
	key := GetAppointDailyRecordKey(platform, channel, daily, op)
	return mdb.RDB.Get(context.Background(), key).Int64()
}

func SetDailyRecordUserHash(platform, channel, userName string, op int) {
	key := GetDailyRecordKey(platform, channel, op)
	mdb.RDB.HSet(context.Background(), key, userName, int64(1))
}

func SetDailyRecordNewUserRegisterHash(platform, channel, userName, ip string, op int) {
	key := GetDailyRecordKey(platform, channel, op)
	mdb.RDB.HSet(context.Background(), key, userName, ip)
}

func SetAppointDailyRecordNewUserRegisterHash(platform, channel, userName, ip string, daily int64, op int) {
	key := GetAppointDailyRecordKey(platform, channel, daily, op)
	err := mdb.RDB.HSet(context.Background(), key, userName, ip).Err()
	if err != nil {
		clog.Errorf("set err:=%v", err)
	}
}

func GetAllDailyRecordNewUserRegister(platform, channel string, op int) (map[string]string, error) {
	key := GetDailyRecordKey(platform, channel, op)
	return mdb.RDB.HGetAll(context.Background(), key).Result()
}

func GetAppointDailyRecordUserHash(platform, channel string, daily int64, op int) (map[string]string, error) {
	key := GetAppointDailyRecordKey(platform, channel, daily, op)
	return mdb.RDB.HGetAll(context.Background(), key).Result()
}

func GetDailyRecordLen(platform, channel string, op int) int64 {
	key := GetDailyRecordKey(platform, channel, op)
	return mdb.RDB.HLen(context.Background(), key).Val()
}

func GetAppointDailyRecordLen(platform, channel string, daily int64, op int) int64 {
	key := GetAppointDailyRecordKey(platform, channel, daily, op)
	return mdb.RDB.HLen(context.Background(), key).Val()
}

func GetTotalPlayerRecordKey(platform, channel string) string {
	return fmt.Sprintf("%v:%v:%v", constant.PlayerStatHKey, platform, channel)
}

func GetTotalPlayerLevelRecordKey(platform, channel string) string {
	return fmt.Sprintf("%v:%v:%v", constant.PlayerLevelStatHKey, platform, channel)
}

func GetTotalPlayerRecordLen(platform, channel string) int64 {
	key := GetTotalPlayerRecordKey(platform, channel)
	return mdb.RDB.HLen(context.Background(), key).Val()
}

func SetTotalPlayerRecord(platform, channel, userName string, level int) {
	key := GetTotalPlayerRecordKey(platform, channel)
	mdb.RDB.HSet(context.Background(), key, userName, int64(level))
}

func GetAllTotalPlayerRecord(platform, channel string) (map[string]string, error) {
	key := GetTotalPlayerRecordKey(platform, channel)
	return mdb.RDB.HGetAll(context.Background(), key).Result()
}

func GetServerRecordKey(nodeId int) string {
	return fmt.Sprintf("%v:%v", constant.ServerLoadHKey, nodeId)
}

func SetServerRecord(nodeId string, num int) {
	mdb.RDB.HSet(context.Background(), constant.ServerLoadHKey, nodeId, num)
}

func GetAllServerRecord() (map[string]string, error) {
	return mdb.RDB.HGetAll(context.Background(), constant.ServerLoadHKey).Result()
}

func SetPlayerBlacklistIpRecord(ip, userName string) (int64, bool) {
	ret, ok := data.RuleConfig.Get(1)
	if !ok {
		return 0, false
	}
	key := fmt.Sprintf("%v:%v", constant.PlayerIpRecordKey, ip)
	mdb.RDB.HIncrBy(context.Background(), key, userName, 1)
	mdb.RDB.Expire(context.Background(), key, time.Duration(ret.MaxTime)*24*time.Hour)
	num := mdb.RDB.HLen(context.Background(), key).Val()
	if int(num) > ret.Num {
		return num, true
	}
	return 0, false
}
