package models

// userapp 是工程名称
// models 是 userapp 下的一个包，包含了用户相关的结构体和函数
// common 是 models 下的一个包，包含了 Base 结构体
import (
	"fmt"
	"userapp/models/common"

	"golang.org/x/crypto/bcrypt"
)

// password 字段是私有的，外部无法直接访问，可以通过 NewUser 函数来创建用户对象，并设置密码
func NewUser(name, email string, age int, pwd string) *User {
	return &User{
		Name:     name,
		Email:    email,
		Age:      age,
		password: pwd, // 内部使用私有函数
	}
}

type User struct {
	// 嵌套 common.Base 结构体，包含 ID、CreatedAt 和 UpdatedAt 字段
	common.Base

	Name  string
	Email string
	Age   int

	// 私有字段（包外不可访问）
	password string
}

// GetPasswordHash 公开方法：获取密码哈希（受控访问）
// 通过这个方法，外部代码可以获取密码的哈希值，但无法直接获取明文密码
// 这种设计可以保护密码字段的安全性，同时提供必要的访问接口
// 核心是我们可以直接控制密码访问的逻辑
func (u *User) GetPasswordHash() string {
	fmt.Println("获取密码")

	// 使用 bcrypt 库对密码进行加密
	// 当前我们引入我新的库的时候，go mod tidy 会自动下载并更新 go.mod 和 go.sum 文件
	bcryptPwd, _ := bcrypt.GenerateFromPassword([]byte(u.password), bcrypt.DefaultCost)
	return string(bcryptPwd)
}

// SetPasswordHash 公开方法：设置密码（受控访问）
func (u *User) SetPasswordHash(password string) {
	fmt.Println("设置密码")
	u.password = password
}

// CheckPasswordHash 公开方法：检查密码哈希是否匹配
// 真实的场景，数据库里面不会存储用户的明文密码，而是存储密码的哈希值。
// 我们判断一个用户的密码是否正确，是通过比对 hash
// plan_password 是用户输入的明文密码 -- hash -> u.GetPasswordHash() 来模拟数据库存储的密码哈希值
// bcrypt.CompareHashAndPassword() 函数会将用户输入的明文密码进行哈希计算，并与存储的哈希值进行比较，如果匹配则返回 nil，否则返回错误
func (u *User) CheckPasswordHash(password string) bool {
	fmt.Println("检查密码")
	err := bcrypt.CompareHashAndPassword([]byte(u.GetPasswordHash()), []byte(password))
	return err == nil
}

func init() {
	// newUserWithDB()
	fmt.Println("models 包的 init 函数被调用")
}
