"""管理员 Management Token 管理端点"""

from dataclasses import dataclass
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, Query, Request
from fastapi.responses import JSONResponse
from sqlalchemy.orm import Session

from src.api.base.admin_adapter import AdminApiAdapter
from src.api.base.context import ApiRequestContext
from src.api.base.pipeline import ApiRequestPipeline
from src.core.exceptions import NotFoundException
from src.database import get_db
from src.models.database import AuditEventType, ManagementToken, User
from src.services.management_token import ManagementTokenService, token_to_dict

router = APIRouter(prefix="/api/admin/management-tokens", tags=["Admin - Management Tokens"])
pipeline = ApiRequestPipeline()


# ============== 安全基类 ==============


class AdminManagementTokenApiAdapter(AdminApiAdapter):
    """管理员 Management Token 管理 API 的基类

    安全限制：禁止使用 Management Token 调用这些接口。
    """

    def authorize(self, context: ApiRequestContext) -> None:
        # 先调用父类的认证和权限检查
        super().authorize(context)

        # 禁止使用 Management Token 调用 management-tokens 相关接口
        if context.management_token is not None:
            raise HTTPException(
                status_code=403,
                detail="不允许使用 Management Token 管理其他 Token，请使用 Web 界面或 JWT 认证",
            )


# ============== 路由 ==============


@router.get("")
async def list_all_management_tokens(
    request: Request,
    user_id: Optional[str] = Query(None, description="筛选用户 ID"),
    is_active: Optional[bool] = Query(None, description="筛选激活状态"),
    skip: int = Query(0, ge=0),
    limit: int = Query(50, ge=1, le=100),
    db: Session = Depends(get_db),
):
    """列出所有 Management Tokens（管理员）

    管理员查看所有用户的 Management Tokens，支持筛选和分页。

    **查询参数**
    - user_id (Optional[str]): 筛选指定用户 ID 的 tokens
    - is_active (Optional[bool]): 筛选激活状态（true/false）
    - skip (int): 分页偏移量，默认 0
    - limit (int): 每页数量，范围 1-100，默认 50

    **返回字段**
    - items (List[dict]): Token 列表
        - id (str): Token ID
        - user_id (str): 所属用户 ID
        - user (dict): 用户信息（包含 id, username, email 等）
        - name (str): Token 名称
        - description (Optional[str]): 描述
        - token_hash (str): Token 哈希值（不返回明文）
        - is_active (bool): 是否激活
        - allowed_ips (Optional[List[str]]): IP 白名单
        - expires_at (Optional[str]): 过期时间（ISO 8601 格式）
        - last_used_at (Optional[str]): 最后使用时间
        - created_at (str): 创建时间
        - updated_at (str): 更新时间
    - total (int): 总数量
    - skip (int): 当前偏移量
    - limit (int): 当前每页数量
    """
    adapter = AdminListManagementTokensAdapter(
        user_id=user_id, is_active=is_active, skip=skip, limit=limit
    )
    return await pipeline.run(adapter=adapter, http_request=request, db=db, mode=adapter.mode)


@router.get("/{token_id}")
async def get_management_token(
    token_id: str,
    request: Request,
    db: Session = Depends(get_db),
):
    """获取 Management Token 详情（管理员）

    管理员查看任意 Management Token 的详细信息。

    **路径参数**
    - token_id (str): Token ID

    **返回字段**
    - id (str): Token ID
    - user_id (str): 所属用户 ID
    - user (dict): 用户信息（包含 id, username, email 等）
    - name (str): Token 名称
    - description (Optional[str]): 描述
    - token_hash (str): Token 哈希值（不返回明文）
    - is_active (bool): 是否激活
    - allowed_ips (Optional[List[str]]): IP 白名单
    - expires_at (Optional[str]): 过期时间（ISO 8601 格式）
    - last_used_at (Optional[str]): 最后使用时间
    - created_at (str): 创建时间
    - updated_at (str): 更新时间
    """
    adapter = AdminGetManagementTokenAdapter(token_id=token_id)
    return await pipeline.run(adapter=adapter, http_request=request, db=db, mode=adapter.mode)


@router.delete("/{token_id}")
async def delete_management_token(
    token_id: str, request: Request, db: Session = Depends(get_db)
):
    """删除任意 Management Token（管理员）

    管理员可以删除任意用户的 Management Token。

    **路径参数**
    - token_id (str): 要删除的 Token ID

    **返回字段**
    - message (str): 操作结果消息
    """
    adapter = AdminDeleteManagementTokenAdapter(token_id=token_id)
    return await pipeline.run(adapter=adapter, http_request=request, db=db, mode=adapter.mode)


@router.patch("/{token_id}/status")
async def toggle_management_token(
    token_id: str, request: Request, db: Session = Depends(get_db)
):
    """切换任意 Management Token 状态（管理员）

    管理员可以启用/禁用任意用户的 Management Token。

    **路径参数**
    - token_id (str): Token ID

    **返回字段**
    - message (str): 操作结果消息（"Token 已启用" 或 "Token 已禁用"）
    - data (dict): 更新后的 Token 信息
        - id (str): Token ID
        - user_id (str): 所属用户 ID
        - user (dict): 用户信息
        - name (str): Token 名称
        - description (Optional[str]): 描述
        - token_hash (str): Token 哈希值
        - is_active (bool): 是否激活（已切换后的状态）
        - allowed_ips (Optional[List[str]]): IP 白名单
        - expires_at (Optional[str]): 过期时间
        - last_used_at (Optional[str]): 最后使用时间
        - created_at (str): 创建时间
        - updated_at (str): 更新时间
    """
    adapter = AdminToggleManagementTokenAdapter(token_id=token_id)
    return await pipeline.run(adapter=adapter, http_request=request, db=db, mode=adapter.mode)


# ============== 适配器 ==============


@dataclass
class AdminListManagementTokensAdapter(AdminManagementTokenApiAdapter):
    """列出所有 Management Tokens"""

    name: str = "admin_list_management_tokens"
    user_id: Optional[str] = None
    is_active: Optional[bool] = None
    skip: int = 0
    limit: int = 50

    async def handle(self, context: ApiRequestContext):
        # 构建查询
        query = context.db.query(ManagementToken)

        if self.user_id:
            query = query.filter(ManagementToken.user_id == self.user_id)
        if self.is_active is not None:
            query = query.filter(ManagementToken.is_active == self.is_active)

        total = query.count()
        tokens = (
            query.order_by(ManagementToken.created_at.desc())
            .offset(self.skip)
            .limit(self.limit)
            .all()
        )

        # 预加载用户信息
        user_ids = list(set(t.user_id for t in tokens))
        users = {u.id: u for u in context.db.query(User).filter(User.id.in_(user_ids)).all()}
        for token in tokens:
            token.user = users.get(token.user_id)

        return JSONResponse(
            content={
                "items": [token_to_dict(t, include_user=True) for t in tokens],
                "total": total,
                "skip": self.skip,
                "limit": self.limit,
            }
        )


@dataclass
class AdminGetManagementTokenAdapter(AdminManagementTokenApiAdapter):
    """获取 Management Token 详情"""

    name: str = "admin_get_management_token"
    token_id: str = ""

    async def handle(self, context: ApiRequestContext):
        token = ManagementTokenService.get_token_by_id(
            db=context.db, token_id=self.token_id
        )

        if not token:
            raise NotFoundException("Management Token 不存在")

        # 加载用户信息
        token.user = context.db.query(User).filter(User.id == token.user_id).first()

        return JSONResponse(content=token_to_dict(token, include_user=True))


@dataclass
class AdminDeleteManagementTokenAdapter(AdminManagementTokenApiAdapter):
    """删除 Management Token"""

    name: str = "admin_delete_management_token"
    token_id: str = ""
    audit_success_event = AuditEventType.MANAGEMENT_TOKEN_DELETED

    async def handle(self, context: ApiRequestContext):
        # 先获取 token 信息用于审计
        token = ManagementTokenService.get_token_by_id(
            db=context.db, token_id=self.token_id
        )

        if not token:
            raise NotFoundException("Management Token 不存在")

        context.add_audit_metadata(
            token_id=token.id,
            token_name=token.name,
            owner_user_id=token.user_id,
        )

        success = ManagementTokenService.delete_token(
            db=context.db, token_id=self.token_id
        )

        if not success:
            raise NotFoundException("Management Token 不存在")

        return JSONResponse(content={"message": "删除成功"})


@dataclass
class AdminToggleManagementTokenAdapter(AdminManagementTokenApiAdapter):
    """切换 Management Token 状态"""

    name: str = "admin_toggle_management_token"
    token_id: str = ""
    audit_success_event = AuditEventType.MANAGEMENT_TOKEN_UPDATED

    async def handle(self, context: ApiRequestContext):
        token = ManagementTokenService.toggle_status(
            db=context.db, token_id=self.token_id
        )

        if not token:
            raise NotFoundException("Management Token 不存在")

        # 加载用户信息
        token.user = context.db.query(User).filter(User.id == token.user_id).first()

        context.add_audit_metadata(
            token_id=token.id,
            token_name=token.name,
            owner_user_id=token.user_id,
            is_active=token.is_active,
        )

        return JSONResponse(
            content={
                "message": f"Token 已{'启用' if token.is_active else '禁用'}",
                "data": token_to_dict(token, include_user=True),
            }
        )
