package mcp

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
)

// tokenRawLen 是 plaintext 随机字节长度。32 字节 = 256 bit 熵，
// base64.RawURL 编码后 43 字符（无 padding）；加 "mcpt_" 前缀总 48 字符。
//
// 与 user.NewSessionToken 的 24 字节比，MCP token 加大到 32 字节是因为：
// admin 签发的 token 长期存在（90 天默认），熵预算更宽。
const tokenRawLen = 32

// tokenPrefix 是 plaintext 的肉眼可读前缀。鉴权时不参与 hash 计算 —— hash
// 是对完整字符串（含前缀）做 SHA-256；前缀仅是日志/调试时区分用。
const tokenPrefix = "mcpt_"

// NewToken 生成 (plaintext, hash) 对。plaintext 仅在签发时返回一次，
// 后续认证只用 hash 反查。
func NewToken() (plaintext string, hash []byte, err error) {
	raw := make([]byte, tokenRawLen)
	if _, err := rand.Read(raw); err != nil {
		return "", nil, fmt.Errorf("rand: %w", err)
	}
	enc := base64.RawURLEncoding.EncodeToString(raw)
	plain := tokenPrefix + enc
	return plain, HashToken(plain), nil
}

// HashToken 对 token plaintext（含前缀）做 SHA-256，返回 32 字节固定长度。
// 纯函数：相同输入恒返回相同输出，便于鉴权时按请求中的明文反查 DB。
func HashToken(plaintext string) []byte {
	sum := sha256.Sum256([]byte(plaintext))
	return sum[:]
}
