"""RBAC 权限：角色层级 + FastAPI 依赖注入（支持平台侧 + 租户侧对称权限）"""
from __future__ import annotations

import contextvars
from enum import Enum

from fastapi import Depends, HTTPException
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.security import decode_token
from app.core.tenant_context import tenant_ctx
from app.db import get_db


# ── 租户侧角色 ──

class TenantRole(str, Enum):
    OWNER = "owner"
    ADMIN = "admin"
    EDITOR = "editor"
    VIEWER = "viewer"


ROLE_HIERARCHY: dict[TenantRole, int] = {
    TenantRole.OWNER: 4,
    TenantRole.ADMIN: 3,
    TenantRole.EDITOR: 2,
    TenantRole.VIEWER: 1,
}


# ── 平台侧角色 ──

class PlatformRole(str, Enum):
    OWNER = "platform_owner"    # 平台所有者：全面权限，可设平台角色
    ADMIN = "platform_admin"    # 平台管理：除角色管理外所有操作
    OPERATOR = "platform_op"    # 平台运营：内容/管道/统计
    VIEWER = "platform_viewer"  # 平台只读：统计和查看


PLATFORM_ROLE_HIERARCHY: dict[PlatformRole, int] = {
    PlatformRole.OWNER: 4,
    PlatformRole.ADMIN: 3,
    PlatformRole.OPERATOR: 2,
    PlatformRole.VIEWER: 1,
}


# ── 统一权限矩阵 ──

PERMISSION_MATRIX: dict[str, set] = {
    # 平台侧权限
    "platform.role.manage":   {PlatformRole.OWNER},
    "platform.tenant.write":  {PlatformRole.OWNER, PlatformRole.ADMIN},
    "platform.user.write":    {PlatformRole.OWNER, PlatformRole.ADMIN},
    "platform.config.write":  {PlatformRole.OWNER, PlatformRole.ADMIN},
    "platform.pipeline.run":  {PlatformRole.OWNER, PlatformRole.ADMIN, PlatformRole.OPERATOR},
    "platform.content.write": {PlatformRole.OWNER, PlatformRole.ADMIN, PlatformRole.OPERATOR},
    "platform.notify.send":   {PlatformRole.OWNER, PlatformRole.ADMIN, PlatformRole.OPERATOR},
    "platform.feedback.manage":{PlatformRole.OWNER, PlatformRole.ADMIN, PlatformRole.OPERATOR},
    "platform.stats.view":    {PlatformRole.OWNER, PlatformRole.ADMIN, PlatformRole.OPERATOR, PlatformRole.VIEWER},

    # 租户侧权限
    "tenant.billing":         {TenantRole.OWNER},
    "tenant.dissolve":        {TenantRole.OWNER},
    "tenant.member.invite":   {TenantRole.OWNER, TenantRole.ADMIN},
    "tenant.member.remove":   {TenantRole.OWNER, TenantRole.ADMIN},
    "tenant.member.role":     {TenantRole.OWNER, TenantRole.ADMIN},
    "tenant.folder.share":    {TenantRole.OWNER, TenantRole.ADMIN},
    "tenant.audit.view":      {TenantRole.OWNER, TenantRole.ADMIN},
    "tenant.jc.submit":       {TenantRole.OWNER, TenantRole.ADMIN, TenantRole.EDITOR},
    "tenant.mdt.create":      {TenantRole.OWNER, TenantRole.ADMIN, TenantRole.EDITOR},
    "tenant.review.create":   {TenantRole.OWNER, TenantRole.ADMIN, TenantRole.EDITOR},
    "tenant.literature.save": {TenantRole.OWNER, TenantRole.ADMIN, TenantRole.EDITOR},
    "tenant.note.create":     {TenantRole.OWNER, TenantRole.ADMIN, TenantRole.EDITOR},
    "tenant.read":            {TenantRole.OWNER, TenantRole.ADMIN, TenantRole.EDITOR, TenantRole.VIEWER},
}


_security = HTTPBearer(auto_error=False)
_current_user_ctx: contextvars.ContextVar[dict | None] = contextvars.ContextVar("_current_user", default=None)


async def get_current_user(
    credentials: HTTPAuthorizationCredentials | None = Depends(_security),
) -> dict:
    """从 JWT 提取当前用户信息"""
    if credentials is None:
        raise HTTPException(status_code=401, detail="Not authenticated")
    try:
        payload = decode_token(credentials.credentials)
        if payload.get("type") != "access":
            raise HTTPException(status_code=401, detail="Invalid token type")
        # 检查 Token 是否已被加入黑名单（logout 后不可重用）
        jti = payload.get("jti")
        if jti:
            from app.core.token_store import token_store
            if await token_store.is_blacklisted(jti):
                raise HTTPException(status_code=401, detail="Token has been revoked")
        # 将租户ID注入全局上下文
        tid = payload.get("tid")
        if tid:
            tenant_ctx.set(tid)
        _current_user_ctx.set(payload)
        return payload
    except HTTPException:
        raise
    except Exception:
        raise HTTPException(status_code=401, detail="Invalid or expired token")


# ── 平台角色保护依赖 ──

class RequirePlatformRole:
    """FastAPI 依赖：强制最低平台角色"""

    def __init__(self, minimum_role: PlatformRole):
        self.minimum_role = minimum_role

    async def __call__(self, current_user: dict = Depends(get_current_user)):
        role_value = current_user.get("platform_role")
        if not role_value:
            raise HTTPException(status_code=403, detail="No platform access")
        try:
            role = PlatformRole(role_value)
        except ValueError:
            raise HTTPException(status_code=403, detail="Invalid platform role")
        if PLATFORM_ROLE_HIERARCHY[role] < PLATFORM_ROLE_HIERARCHY[self.minimum_role]:
            raise HTTPException(status_code=403, detail="Insufficient platform permissions")
        return current_user


require_platform_role = RequirePlatformRole

# 便捷别名
require_platform_owner = RequirePlatformRole(PlatformRole.OWNER)
require_platform_admin = RequirePlatformRole(PlatformRole.ADMIN)
require_platform_operator = RequirePlatformRole(PlatformRole.OPERATOR)
require_platform_viewer = RequirePlatformRole(PlatformRole.VIEWER)


# ── 租户角色保护依赖（保留原有逻辑） ──

class RequireRole:
    """FastAPI 依赖：强制当前租户内最低角色"""

    def __init__(self, minimum_role: TenantRole):
        self.minimum_role = minimum_role

    async def __call__(self, _user: dict = Depends(get_current_user), db: AsyncSession = Depends(get_db)):
        tid = tenant_ctx.get()
        if tid is None:
            return None

        import uuid as _uuid

        from app.models.user import UserTenant
        result = await db.execute(
            select(UserTenant.role).where(
                UserTenant.user_id == _uuid.UUID(_user["sub"]),
                UserTenant.tenant_id == (_uuid.UUID(tid) if isinstance(tid, str) else tid),
            )
        )
        role_name = result.scalar()
        if role_name is None:
            raise HTTPException(status_code=403, detail="Not a member of this tenant")

        try:
            role = TenantRole(role_name)
        except ValueError:
            raise HTTPException(status_code=403, detail="Invalid role")

        if ROLE_HIERARCHY[role] < ROLE_HIERARCHY[self.minimum_role]:
            raise HTTPException(status_code=403, detail="Insufficient permissions")
        return role_name


require_role = RequireRole
