package domain

import "strings"

// RedisKey is the permission module Redis key prefix. Use the package-level
// helpers (Get*RedisKey) instead of string concatenation so the layout stays
// auditable.
type RedisKey string

// Key prefixes for the permission module. Layout matches
// internal/model/permission/SDD.md §4.1 (Redis Keys).
const (
	CasbinRulesRedisKey  RedisKey = "permission:casbin:rules"
	UserRolesRedisKey    RedisKey = "perm:user_roles"
	RolePermsRedisKey    RedisKey = "perm:role_perms"
	PermissionTreeKey    RedisKey = "permission:tree:open"
	PolicyReloadLockKey  RedisKey = "permission:policy:reload:lock"
	StepUpUsedRedisKey   RedisKey = "permission:stepup:used"
	PermissionAuthGenKey RedisKey = "auth:gen"
)

// With appends colon-separated parts to the key.
func (key RedisKey) With(parts ...string) RedisKey {
	if len(parts) == 0 {
		return key
	}
	return RedisKey(string(key) + ":" + strings.Join(parts, ":"))
}

// String returns the raw key.
func (key RedisKey) String() string {
	return string(key)
}

// GetCasbinRulesRedisKey returns the tenant-scoped Casbin policy list key.
func GetCasbinRulesRedisKey(tenantID string) string {
	return CasbinRulesRedisKey.With(tenantID).String()
}

// GetUserRolesRedisKey returns the cache key for a user's role keys.
func GetUserRolesRedisKey(tenantID, uid string) string {
	return UserRolesRedisKey.With(tenantID, uid).String()
}

// GetRolePermsRedisKey returns the cache key for a role's permission names.
func GetRolePermsRedisKey(tenantID, roleID string) string {
	return RolePermsRedisKey.With(tenantID, roleID).String()
}

// GetAuthGenRedisKey returns the auth_gen revocation counter key. It mirrors
// the auth module's namespace because permission changes also bump auth_gen.
func GetAuthGenRedisKey(tenantID, uid string) string {
	return PermissionAuthGenKey.With(tenantID, uid).String()
}
