"""
FastAPI 依赖注入 —— 权限拦截核心
get_current_user: 解析 JWT → 查表获取完整权限上下文
"""

from __future__ import annotations

from fastapi import Depends, Header
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.exceptions import UnauthorizedException
from app.core.security import decode_access_token
from app.db.database import get_db
from app.models.sys import SysUser
from app.schemas.auth import CurrentUserPayload


async def get_current_user(
    authorization: str = Header(..., description="Bearer <token>"),
    db: AsyncSession = Depends(get_db),
) -> CurrentUserPayload:
    """
    核心鉴权依赖：
    1. 从 Header 提取 Bearer Token
    2. 解码 JWT 拿到 user_id
    3. 查 sys_users + 联表 role/dept 拿到 data_scope 等完整上下文
    4. 返回 CurrentUserPayload 供业务层使用
    """
    # ── 解析 Bearer Token ──
    if not authorization.startswith("Bearer "):
        raise UnauthorizedException("Authorization 格式错误，需为 Bearer <token>")

    token = authorization.removeprefix("Bearer ").strip()
    payload = decode_access_token(token)
    if payload is None:
        raise UnauthorizedException("Token 无效或已过期")

    user_id: str | None = payload.get("sub")
    if user_id is None:
        raise UnauthorizedException("Token 载荷缺少 sub 字段")

    # ── 查库获取用户及关联角色 ──
    stmt = (
        select(SysUser)
        .where(SysUser.id == user_id, SysUser.is_deleted.is_(False))
    )
    result = await db.execute(stmt)
    user = result.scalar_one_or_none()

    if user is None:
        raise UnauthorizedException("用户不存在或已被停用")
    if user.status != 1:
        raise UnauthorizedException("账号已被禁用")

    # ── 组装权限上下文 ──
    return CurrentUserPayload(
        user_id=user.id,
        username=user.username,
        real_name=user.real_name,
        dept_id=user.dept_id,
        dept_name=user.department.name if user.department else None,
        role_id=user.role_id,
        role_name=user.role.role_name if user.role else None,
        data_scope=user.role.data_scope if user.role else "self",
        menu_keys=user.role.menu_keys if user.role else [],
    )
