package operation

import (
	"context"
	"errors"
	"fmt"
	"game/common/model/user"
	"game/common/modelOperator"
	"game/common/proto/pb"
	"game/common/utils"
	"github.com/fox/fox/log"
	"github.com/fox/fox/xrand"
	"github.com/go-redis/redis/v8"
	"github.com/google/uuid"
	"gorm.io/gorm"
	"strconv"
)

type UserOp struct {
	db        *gorm.DB
	userRedis *redis.Client
	*modelOperator.TableOp[user.User]
}

// 玩家表
func NewUserOp() *UserOp {
	return &UserOp{
		db:        UserDB,
		userRedis: UserRedis,
		TableOp:   modelOperator.NewTableOp[user.User](UserDB, UserRedis),
	}
}

func (s *UserOp) redisKey(accountId int64) string {
	return fmt.Sprintf("account_id:%v", accountId)
}

func (s *UserOp) GetUserByAccountId(accountId int64) (*user.User, pb.ErrCode) {
	sUid, err := s.userRedis.Get(context.Background(), s.redisKey(accountId)).Result()
	if err != nil {
		if errors.Is(err, redis.Nil) {
			us, code := s.FindCondition(map[string]any{"account_id": accountId})
			if code != pb.ErrCode_OK {
				// db中没有则创建玩家
				if us, code = s.createUserAccountId(accountId); code == pb.ErrCode_OK {
					_, _ = NewUserResourcesOp().Create(&user.UserResources{UID: us.ID})
					return us, pb.ErrCode_OK
				} else {
					log.DebugF("create user by account id:%v", accountId)
					return nil, pb.ErrCode_SystemErr
				}
			}
			return us, pb.ErrCode_OK
		} else {
			log.ErrorF("find user by account id:%v err:%v", accountId, err)
			return nil, pb.ErrCode_SystemErr
		}
	}
	uid, _ := strconv.ParseInt(sUid, 10, 64)
	if uid < 0 {
		log.ErrorF("get user failed, account id:%d, uid:%v", accountId, sUid)
		return nil, pb.ErrCode_SystemErr
	}
	return s.Find(uid)
}

func (s *UserOp) generateUniqueNickname(db *gorm.DB) (string, error) {
	// 基础昵称模板
	baseNick := "用户_" + uuid.New().String()[:8]
	nickname := baseNick

	// 检查是否唯一，不唯一则追加随机字符
	for i := 0; i < 5; i++ { // 最多尝试5次
		var count int64
		err := db.Model(&user.User{}).Where("nickname = ?", nickname).Count(&count).Error
		if err != nil {
			return "", err
		}
		if count == 0 {
			return nickname, nil
		}
		nickname = baseNick + xrand.RandomString(2) // 追加2位随机字符
	}

	return "", fmt.Errorf("无法生成唯一昵称")
}

// 创建用户
func (s *UserOp) createUserAccountId(accountId int64) (*user.User, pb.ErrCode) {
	nickname, err := s.generateUniqueNickname(s.db)
	if err != nil {
		log.ErrorF("generate unique nickname err:%v", err)
		return nil, pb.ErrCode_SystemErr
	}
	us := &user.User{
		AccountId: accountId,
		Nickname:  nickname,
	}
	var code pb.ErrCode
	us, code = s.Create(us)
	log.DebugF("create user:%v", utils.JsonMarshal(us))
	if code != pb.ErrCode_OK {
		return nil, code
	}
	// 建立索引
	_ = s.userRedis.Set(context.Background(), s.redisKey(us.AccountId), us.ID, modelOperator.TableExpire).Err()
	return us, pb.ErrCode_OK
}
