package operation

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

type UserAccountOp struct {
	logDb        *gorm.DB
	db           *gorm.DB
	accountRedis *redis.Client
	accountOp    *modelOperator.TableOp[user.UserAccount]
}

func NewUserAccountOp() *UserAccountOp {
	return &UserAccountOp{
		logDb:        LogDB,
		db:           UserDB,
		accountRedis: AccountRedis,
		accountOp:    modelOperator.NewTableOp[user.UserAccount](UserDB, AccountRedis),
	}
}

func (s *UserAccountOp) redisKey(username string) string {
	return fmt.Sprintf("username:%s", username)
}

// 创建用户
func (s *UserAccountOp) Find(uid int64) (*user.UserAccount, pb.ErrCode) {
	us, code := s.accountOp.Find(uid)
	if us != nil {
		us.Password = ""
	}
	return us, code
}

func (s *UserAccountOp) GetUserAccount(username string) (*user.UserAccount, pb.ErrCode) {
	sUid, err := s.accountRedis.Get(context.Background(), s.redisKey(username)).Result()
	if err != nil {
		if errors.Is(err, redis.Nil) {
			us := &user.UserAccount{}
			err = s.db.Where("username = ?", username).First(us).Error
			if err != nil {
				if errors.Is(err, gorm.ErrRecordNotFound) {
					return nil, pb.ErrCode_AccountNotExist
				}
				log.DebugF("find user:%v err:%v", username, err)
				return nil, pb.ErrCode_SystemErr
			}
			// 从db中查到后写入redis，并建立索引
			if us.Username != "" && us.ID > 0 {
				_, _ = s.accountOp.Update(us.ID, serialization.StructToMap(us))
				_ = s.accountRedis.Set(context.Background(), s.redisKey(username), us.ID, modelOperator.TableExpire).Err()
			}
			return us, pb.ErrCode_OK
		} else {
			log.ErrorF("find user:%v err:%v", username, err)
			return nil, pb.ErrCode_SystemErr
		}
	}
	uid, _ := strconv.ParseInt(sUid, 10, 64)
	if uid < 0 {
		log.ErrorF("get user account:%v failed, uid is: %d", username, uid)
		return nil, pb.ErrCode_SystemErr
	}
	return s.accountOp.Find(uid)
}

// 创建用户
func (s *UserAccountOp) CreateUserAccount(us *user.UserAccount) (*user.UserAccount, pb.ErrCode) {
	// 密码加密
	hashedPassword, err := utils.Password(us.Password)
	if err != nil {
		log.ErrorF("username :%v generate password err:%v", us.Username, err)
		return nil, pb.ErrCode_SystemErr
	}
	us.Password = hashedPassword
	var code pb.ErrCode
	us, code = s.accountOp.Create(us)
	log.DebugF("create user:%v", utils.JsonMarshal(us))
	if code != pb.ErrCode_OK {
		return nil, code
	}
	// 建立索引
	_ = s.accountRedis.Set(context.Background(), s.redisKey(us.Username), us.ID, modelOperator.TableExpire).Err()
	return us, pb.ErrCode_OK
}

// 更新密码
func (s *UserAccountOp) UpdateUserPassword(us *user.UserAccount) (*user.UserAccount, pb.ErrCode) {
	// 密码加密
	hashedPassword, err := utils.Password(us.Password)
	if err != nil {
		log.ErrorF("username :%v generate password err:%v", us.Username, err)
		return nil, pb.ErrCode_SystemErr
	}
	var code pb.ErrCode
	us, code = s.accountOp.Update(us.ID, map[string]any{"password": hashedPassword})
	if code != pb.ErrCode_OK {
		_ = s.accountRedis.Expire(context.Background(), s.redisKey(us.Username), modelOperator.TableExpire).Err()
	}
	return us, code
}

// 记录登录日志
func (s *UserAccountOp) RecordLoginLog(logEntry *user.UserLoginLog) {
	if err := s.logDb.Create(&logEntry).Error; err != nil {
		log.ErrorF("记录登录日志失败: %v", err)
	}
}

//
//// 生成JWT令牌(简化版)
//func generateToken(userID uint, username string) (string, error) {
//	_ = userID
//	_ = username
//	// 这里应该使用JWT库生成实际令牌
//	// 简化实现，实际项目中请使用安全的JWT实现
//	return "generated-token-placeholder", nil
//}
