"""Authentication endpoints for third-party system integration.

第三方系统认证端点。
提供 SSO 令牌交换接口，允许已认证的外部系统为其用户获取本系统 JWT。

三方系统传入的 ID 通常是纯数字（如 user_id=1001, dept_id=5），
本接口会自动添加类型前缀（U_、O_、D_、A_、R_）以匹配内部 ACL 体系。
"""

from __future__ import annotations

from fastapi import APIRouter
from pydantic import BaseModel, Field

from app.core.security import TokenClaims, create_access_token
from app.utils.logger import get_logger

logger = get_logger(__name__)

router = APIRouter(prefix="/auth", tags=["auth"])


# ── ID 前缀常量 ──────────────────────────────────────────────────────────────

PREFIX_USER = "U_"
PREFIX_OFFICE = "O_"
PREFIX_DEPT = "D_"
PREFIX_AREA = "A_"
PREFIX_ROLE = "R_"


def ensure_prefix(value: str, prefix: str) -> str:
    """为 ID 添加类型前缀（如已存在则不重复添加）。

    >>> ensure_prefix("1001", "U_")
    'U_1001'
    >>> ensure_prefix("U_1001", "U_")
    'U_1001'
    >>> ensure_prefix("", "U_")
    ''
    """
    if not value:
        return value
    return value if value.startswith(prefix) else f"{prefix}{value}"


# ── Schemas ──────────────────────────────────────────────────────────────────


class SSOTokenRequest(BaseModel):
    """Request body for SSO token exchange.

    第三方系统传入的用户身份信息。ID 字段可以是纯数字（如 ``"1001"``），
    服务端会自动添加类型前缀（``U_``、``O_``、``D_``、``A_``、``R_``）。
    """

    user_id: str = Field(..., min_length=1, description="用户唯一标识（纯数字即可，如 1001）")
    user_name: str = Field(default="", description="用户姓名")
    office_id: str = Field(default="", description="科室 ID（纯数字即可，如 17）")
    office_name: str = Field(default="", description="科室名称")
    dept_id: str = Field(default="", description="部门 ID（纯数字即可，如 5）")
    dept_name: str = Field(default="", description="部门名称")
    area_id: str = Field(default="", description="地区 ID（纯数字即可，如 1）")
    area_name: str = Field(default="", description="地区名称")
    role_ids: list[str] = Field(default_factory=list, description="角色 ID 列表（纯数字即可，如 [\"1\", \"3\"]）")


class SSOTokenResponse(BaseModel):
    """Response containing the issued JWT.

    签发的 JWT 令牌响应。user_id 为添加前缀后的内部 ID。
    """

    access_token: str
    token_type: str = "bearer"
    expires_in: int
    user_id: str


# ── Endpoint ─────────────────────────────────────────────────────────────────


@router.post("/sso", response_model=SSOTokenResponse)
async def sso_token_exchange(body: SSOTokenRequest) -> SSOTokenResponse:
    """Exchange third-party user info for a zm-rag JWT.

    第三方系统调用此接口，传入用户信息，换取本系统的 JWT 令牌。
    返回的令牌可直接用于所有需要认证的接口。

    **ID 自动前缀**：三方系统传入的原始 ID（通常为纯数字）会被自动添加
    类型前缀以匹配内部 ACL 体系：

    - ``user_id``  → ``U_<id>``
    - ``office_id`` → ``O_<id>``
    - ``dept_id``  → ``D_<id>``
    - ``area_id``  → ``A_<id>``
    - ``role_ids`` → ``R_<id>``

    当前版本不要求调用方身份验证（无 app_id/secret），
    后续可通过中间件或依赖注入添加。
    """
    # 为三方系统传入的原始 ID 添加类型前缀
    prefixed_user_id = ensure_prefix(body.user_id, PREFIX_USER)
    prefixed_office_id = ensure_prefix(body.office_id, PREFIX_OFFICE)
    prefixed_dept_id = ensure_prefix(body.dept_id, PREFIX_DEPT)
    prefixed_area_id = ensure_prefix(body.area_id, PREFIX_AREA)
    prefixed_role_ids = [ensure_prefix(r, PREFIX_ROLE) for r in body.role_ids]

    claims = TokenClaims(
        user_id=prefixed_user_id,
        user_name=body.user_name,
        office_id=prefixed_office_id,
        office_name=body.office_name,
        dept_id=prefixed_dept_id,
        dept_name=body.dept_name,
        area_id=prefixed_area_id,
        area_name=body.area_name,
        role_ids=prefixed_role_ids,
    )

    result = create_access_token(claims, issuer="zm-rag")

    logger.info(
        "sso_token_issued",
        user_id=prefixed_user_id,
        office_id=prefixed_office_id,
        dept_id=prefixed_dept_id,
        area_id=prefixed_area_id,
    )

    return SSOTokenResponse(
        access_token=result.access_token,
        token_type="bearer",
        expires_in=result.expires_in,
        user_id=prefixed_user_id,
    )
