package users

import (
	"context"
	"crypto/rand"
	"encoding/hex"

	v1 "hotgo/api/api/users/v1"
	"hotgo/internal/consts"
	"hotgo/internal/dao"
	"hotgo/internal/model/entity"
	utility "hotgo/utility/jwt"

	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/os/gtime"
)

// 生成随机 salt
func generateSalt(n int) (string, error) {
	b := make([]byte, n)
	_, err := rand.Read(b)
	if err != nil {
		return "", err
	}
	return hex.EncodeToString(b), nil
}

func (c *ControllerV1) Register(ctx context.Context, req *v1.RegisterReq) (res *v1.RegisterRes, err error) {
	// 0. 检查两次密码是否一致
	if req.Password != req.ConfirmPassword {
		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "两次密码输入不一致")
	}
	// 1. 检查手机号是否已注册
	count, err := dao.Users.Ctx(ctx).Where("phone = ?", req.Phone).Count()
	if err != nil {
		return nil, gerror.NewCode(gcode.CodeDbOperationError, "数据库错误")
	}
	if count > 0 {
		return nil, gerror.NewCode(consts.CodeUserAlreadyExists, "手机号已注册")
	}

	// 2. 生成 salt 并加密密码
	salt, err := generateSalt(8)
	if err != nil {
		return nil, gerror.NewCode(gcode.CodeInternalError, "生成salt失败")
	}
	hashedPwd := utility.HashPassword(req.Password, salt)

	// 3. 写入用户表
	user := entity.Users{
		Phone:      req.Phone,
		Password:   hashedPwd,
		Salt:       salt,
		Nickname:   "用户" + req.Phone,
		Avatar:     "https://cdn.jsdelivr.net/gh/hotgo-io/hotgo-cdn@main/avatar/default.png",
		Status:     1,
		Introduce:  "这个人很懒，什么都没有留下",
		Gender:     0,
		LoginCount: 0,
		LastLogin:  gtime.Now(),
	}

	userId, err := dao.Users.Ctx(ctx).Data(user).InsertAndGetId()
	if err != nil {
		return nil, gerror.NewCode(consts.CodeInternalError, "注册失败")
	}

	// 4. 返回 JWT Token
	token, err := utility.GenerateToken(userId)
	if err != nil {
		return nil, gerror.NewCode(consts.CodeInternalError, "生成Token失败")
	}
	res = &v1.RegisterRes{
		Token: token,
	}
	return
}
