// Package permission — 能力點（capability）與角色預設對照。
//
// 現行策略（M1～M2）：
//   - JWT 帶 roles[]；中介層／業務用 permission.Has(roles, code) 判定
//   - 尚未做 DB 動態 permission 表；擴充時只改本檔 RoleGrants 即可
//
// 命名：{domain}:{resource}:{action} 或 {domain}:{action}
package permission

// ─── 公開／系統（不需登入）────────────────────────────────
const (
	// PublicPing 健康檢查（無 JWT）
	PublicPing = "public:ping"
	// PublicAuthLogin 登入／註冊／忘密／refresh 等公開 auth
	PublicAuthLogin = "public:auth:login"
	// PublicThreadsOAuthCallback OAuth 回調（state 驗證）
	PublicThreadsOAuthCallback = "public:threads:oauth_callback"
)

// ─── 已登入會員（member）──────────────────────────────────
const (
	AuthMe              = "auth:me"
	AuthProfileUpdate   = "auth:profile:update"
	AuthPasswordChange  = "auth:password:change"
	AuthEmailVerify     = "auth:email:verify"
	AuthLogout          = "auth:logout"
	AuthIdentities      = "auth:identities"
	AuthBind            = "auth:bind"
	AuthUnbind          = "auth:unbind"

	MediaUpload = "media:upload"

	SettingsAIRead       = "settings:ai:read"
	SettingsAIWrite      = "settings:ai:write"
	SettingsPlacementRead  = "settings:placement:read"
	SettingsPlacementWrite = "settings:placement:write"
	SettingsModelsList   = "settings:models:list"

	ThreadsOAuthStart = "threads:oauth:start"
	ThreadsList       = "threads:list"
	ThreadsRefresh    = "threads:refresh"
	ThreadsDisconnect = "threads:disconnect"

	JobsList = "jobs:list"
	JobsGet  = "jobs:get"
	// JobsDemoCreate 僅 admin（任務頁「產生測試任務」）
	JobsDemoCreate = "jobs:demo:create"

	NotifList     = "notifications:list"
	NotifUnread   = "notifications:unread"
	NotifMarkRead = "notifications:mark_read"
)

// ─── 管理員（admin）───────────────────────────────────────
const (
	// AdminAccess 進入管理能力的總閘（AdminAuth middleware 檢查此碼）
	AdminAccess = "admin:access"

	AdminMembersList           = "admin:members:list"
	AdminMembersGet            = "admin:members:get"
	AdminMembersCreate         = "admin:members:create"
	AdminMembersSuspend        = "admin:members:suspend"
	AdminMembersRoles          = "admin:members:roles"
	AdminMembersEmailVerified  = "admin:members:email_verified"
	AdminMembersResetPassword  = "admin:members:reset_password"
	AdminMembersIdentities     = "admin:members:identities"
	AdminMembersStatus         = "admin:members:status"
)

// Role names（與 member.domain 一致）
const (
	RoleMember = "member"
	RoleAdmin  = "admin"
)

// memberBase — 一般會員可做的事
var memberBase = []string{
	AuthMe, AuthProfileUpdate, AuthPasswordChange, AuthEmailVerify, AuthLogout,
	AuthIdentities, AuthBind, AuthUnbind,
	MediaUpload,
	SettingsAIRead, SettingsAIWrite, SettingsPlacementRead, SettingsPlacementWrite, SettingsModelsList,
	ThreadsOAuthStart, ThreadsList, ThreadsRefresh, ThreadsDisconnect,
	JobsList, JobsGet,
	NotifList, NotifUnread, NotifMarkRead,
}

// adminExtra — 管理員額外能力
var adminExtra = []string{
	AdminAccess,
	AdminMembersList, AdminMembersGet, AdminMembersCreate,
	AdminMembersSuspend, AdminMembersRoles, AdminMembersEmailVerified,
	AdminMembersResetPassword, AdminMembersIdentities, AdminMembersStatus,
	JobsDemoCreate,
}

// RoleGrants 角色 → 能力列表（可擴充自訂角色）
var RoleGrants = map[string][]string{
	RoleMember: memberBase,
	RoleAdmin:  append(append([]string{}, memberBase...), adminExtra...),
}

// Expand 合併多角色能力（去重）
func Expand(roles []string) map[string]struct{} {
	out := make(map[string]struct{})
	for _, r := range roles {
		for _, p := range RoleGrants[r] {
			out[p] = struct{}{}
		}
	}
	// admin 一定含 AdminAccess
	if hasRole(roles, RoleAdmin) {
		out[AdminAccess] = struct{}{}
	}
	return out
}

func hasRole(roles []string, want string) bool {
	for _, r := range roles {
		if r == want {
			return true
		}
	}
	return false
}

// Has 是否具備指定 permission
func Has(roles []string, code string) bool {
	if code == "" {
		return false
	}
	_, ok := Expand(roles)[code]
	return ok
}

// HasAny 具備任一即可
func HasAny(roles []string, codes ...string) bool {
	set := Expand(roles)
	for _, c := range codes {
		if _, ok := set[c]; ok {
			return true
		}
	}
	return false
}

// HasAll 必須全部具備
func HasAll(roles []string, codes ...string) bool {
	set := Expand(roles)
	for _, c := range codes {
		if _, ok := set[c]; !ok {
			return false
		}
	}
	return true
}

// IsAdmin 是否具管理總閘（相容舊呼叫）
func IsAdmin(roles []string) bool {
	return Has(roles, AdminAccess)
}
