package player

import (
	"errors"
	"gadmin/config"
	"gadmin/internal/admin/consts"
	"gadmin/internal/gorm/model"
	"gadmin/internal/gorm/query"
	model2 "leafstalk/covenant/model"
	"strconv"
	"sync"

	"github.com/sirupsen/logrus"
	"github.com/spf13/cast"
	"gorm.io/gorm"
)

const (
	maxMapStoreLimit = 50000
)

var (
	AllRoleData     = make(map[int]*RoleData, 0)
	lock            sync.RWMutex
	userStampMap    = make(map[int64]int32)
	userChannelLock sync.RWMutex
	userChannelMap  = make(map[int64]string, 0)
)

type RoleData struct {
	ID        int `json:"id"`
	Type      int `json:"type"`
	Evolution int `json:"evolution"`
	Level     int `json:"level"`
	Break     int `json:"break"`
}

// GetRoleData 根据角色ID获取角色信息
func GetRoleData(id int) *RoleData {
	idx := strconv.Itoa(id)
	if len(idx) == 9 {
		level, _ := strconv.Atoi(idx[5:8])

		role := &RoleData{
			ID:        id,
			Type:      cast.ToInt(idx[:1]),
			Evolution: cast.ToInt(idx[4:5]),
			Level:     level,
			Break:     id % 10,
		}

		return role
	}
	if len(idx) == 10 {
		level, _ := strconv.Atoi(idx[6:9])

		role := &RoleData{
			ID:        id,
			Type:      cast.ToInt(idx[:2]),
			Evolution: cast.ToInt(idx[5:6]),
			Level:     level,
			Break:     id % 10,
		}

		return role
	}

	logrus.Warnf("GetRoleData role = nil, id:%+v", id)
	return nil
}

func GetUserChannel(userId int64) string {
	if userId == 0 {
		return "0"
	}

	//if val, ok := userChannelMap[userId]; ok {
	//	return val
	//}

	userChannelLock.RLock()
	defer userChannelLock.RUnlock()

	u := query.Use(config.DB).PlayerChannel
	user, err := u.Where(u.Playerid.Eq(userId)).Select(u.ChannelID).First()
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		logrus.Errorf("GetUserChannel query user failed：%v", err)
		return "0"
	}

	if user == nil {
		logrus.Errorf("GetUserChannel 未查到玩家%v渠道ID..\n", userId)
		return "0"
	} else {
		return user.ChannelID
	}

	//if user == nil {
	//	userChannelMap[userId] = "0"
	//} else {
	//	userChannelMap[userId] = user.ChannelID
	//}
	//
	//if len(userChannelMap) >= maxMapStoreLimit {
	//	userChannelMap = make(map[int64]string, 0)
	//}
	//return userChannelMap[userId]
}

func GetUserStamp(userId int64) int32 {
	if val, ok := userStampMap[userId]; ok {
		return val
	}
	if userId == 0 {
		return 0
	}

	var (
		user *model.PlayerAttr
		err  error
	)

	lock.RLock()
	defer func() {
		if len(userStampMap) > maxMapStoreLimit {
			userStampMap = make(map[int64]int32)
		}
		lock.RUnlock()
	}()

	for _, DB := range config.GDBGroup {
		u := query.Use(DB).PlayerAttr
		user, err = u.Where(u.Playerid.Eq(userId)).Select(u.CreateTime).First()
		if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
			logrus.Errorf("GetUserStamp query user failed：%v", err)
			return 0
		}

		if user == nil {
			continue
		} else {
			userStampMap[userId] = int32(user.CreateTime.Unix())
			break
		}
	}

	if user == nil {
		//userStampMap[userId] = 0
		logrus.Errorf("GetUserStamp 未查到玩家注册时间..")
		return 0
	}

	return userStampMap[userId]
}

// GetServerIDByUserId 通过玩家ID获取所在的数据库
func GetServerIDByUserId(playerId int64) (serverID int32, err error) {
	_, lineId := model2.SplitDocId(playerId)
	if DB, ok := config.GDBGroup[lineId]; ok && DB != nil {
		return int32(lineId), nil
	}
	var models *model.PlayerAttr
	for k, DB := range config.GDBGroup {
		logrus.Warnf("GetDBByUserId DB:%+v", k)
		var (
			q = query.Use(DB).PlayerAttr
			m = q.Where(q.Playerid.Eq(playerId))
		)

		if err = m.Scan(&models); err != nil {
			return
		}

		logrus.Warnf("GetDBByUserId models:%+v", models)
		if models != nil {
			serverID = int32(k)
			break
		}
	}

	if serverID != 0 && models != nil {
		return serverID, nil
	}

	return 0, errors.New("用户不存在")
}

// GetAccIDByUserId 通过玩家ID获取accId
func GetAccIDByUserId(playerId int64) (accID int64, err error) {
	var models *model.PlayerAttr
	for _, DB := range config.GDBGroup {
		var (
			q = query.Use(DB).PlayerAttr
			m = q.Where(q.Playerid.Eq(playerId))
		)

		if err = m.Scan(&models); err != nil {
			return
		}

		if models != nil {
			break
		}
	}

	if models != nil {
		return models.AccID, nil
	}

	return 0, errors.New("用户不存在")
}

// GetAccIDByOpenId 通过openID获取accId
func GetAccIDByOpenId(openID string) (accID int64, err error) {
	var models *model.PlayerAttr
	for _, DB := range config.GDBGroup {
		var (
			q = query.Use(DB).PlayerAttr
			m = q.Where(q.OpenID.Eq(openID))
		)

		if err = m.Scan(&models); err != nil {
			return
		}

		if models != nil {
			break
		}
	}

	if models != nil {
		return models.AccID, nil
	}

	return 0, errors.New("用户不存在")
}

// GetAttrByUserId 通过User获取user attr
func GetAttrByUserId(playerId int64) (attr *model.PlayerAttr, err error) {
	var models *model.PlayerAttr
	for _, DB := range config.GDBGroup {
		var (
			q = query.Use(DB).PlayerAttr
			m = q.Where(q.Playerid.Eq(playerId))
		)

		if err = m.Scan(&models); err != nil {
			return
		}

		if models != nil {
			break
		}
	}

	if models != nil {
		return models, nil
	}

	return nil, errors.New("用户不存在")
}

func GetAccountByAccId(accId int64) (account *model.UserAccount, err error) {
	var models *model.UserAccount
	q := config.LDB.Scopes(model.UserAccountTable(models, accId)).Where("accId = ?", accId)
	if err := q.Scan(&models).Error; err != nil {
		return nil, err
	}
	if models != nil {
		return models, nil
	}
	return nil, errors.New("账号不存在")
}

// GetDBByUserId 通过玩家ID获取所在的数据库
func GetDBByUserId(playerId int64) (Db int, err error) {
	serverID, err := GetServerIDByUserId(playerId)
	if err != nil {
		return 0, err
	}

	if serverID > 0 {
		return GetDBByServerID(int(serverID))
	}

	return 0, errors.New("用户不存在")
}

// GetDBByServerID 通过serverID获取数据库
func GetDBByServerID(serverID int) (int, error) {
	// 目前serverId 和db是对应关系，后面如果不是可以在这里做处理
	return serverID, nil
}

// GetDBByPlayerAttr 通过用户信息获取数据库（兼容合服）
func GetDBByPlayerAttr(playerAttr *model.PlayerAttr) (int, error) {
	// 目前serverId 和db是对应关系，后面如果不是可以在这里做处理
	return int(playerAttr.Line), nil
}

func GetUserFlag(serverID int, userId int64) int32 {
	u := query.Use(config.GDBGroup[serverID]).PlayerAttr
	user, err := u.Where(u.Playerid.Eq(userId)).Select(u.Flag).First()
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		logrus.Errorf("GetUserFlag query user failed：%v", err)
		return 0
	}

	if user == nil {
		return consts.UserFlagOld
	} else {
		return user.Flag
	}
}
