"""
认证路由：登录与令牌刷新。

- POST /api/auth/login  — 验证用户名密码，返回 JWT 令牌对
- POST /api/auth/refresh — 用刷新令牌换取新的访问令牌
"""

import logging

from fastapi import APIRouter, HTTPException, status
from jose import JWTError

from app.auth.jwt import (
    create_access_token,
    create_token_pair,
    decode_refresh_token,
    verify_password,
)
from app.database import get_connection
from app.schemas.auth import LoginRequest, RefreshRequest, TokenResponse

logger = logging.getLogger(__name__)

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


@router.post("/login", response_model=TokenResponse)
async def login(body: LoginRequest):
    """
    用户登录。

    查询 admin_users 表验证用户名密码，成功后返回 JWT 令牌对。
    - 用户不存在或密码错误：401
    - 账号已禁用（is_active=false）：401
    """
    conn = get_connection()
    try:
        with conn.cursor() as cur:
            cur.execute(
                "SELECT id, password_hash, site_id, is_active, roles "
                "FROM admin_users WHERE username = %s",
                (body.username,),
            )
            row = cur.fetchone()
    finally:
        conn.close()

    if row is None:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="用户名或密码错误",
        )

    user_id, password_hash, site_id, is_active, roles = row

    if not is_active:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="账号已被禁用",
        )

    if not verify_password(body.password, password_hash):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="用户名或密码错误",
        )

    tokens = create_token_pair(user_id, site_id, roles=roles or [], audience="admin")
    return TokenResponse(**tokens)


@router.post("/refresh", response_model=TokenResponse)
async def refresh(body: RefreshRequest):
    """
    刷新访问令牌。

    验证 refresh_token 有效性，成功后仅返回新的 access_token
    （refresh_token 保持不变，由客户端继续持有）。
    """
    try:
        # 兼容:旧 token 无 aud(audience=None);新 token 应带 aud="admin"
        # 灰度期暂不强制 aud 校验,Wave 2 切换强制
        payload = decode_refresh_token(body.refresh_token)
    except JWTError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="无效的刷新令牌",
        )

    user_id = int(payload["sub"])
    site_id = payload["site_id"]

    # CHANGE 2026-03-24 | Prompt: 修复 refresh 丢失 roles | 刷新前查询数据库获取最新 roles
    conn = get_connection()
    try:
        with conn.cursor() as cur:
            cur.execute(
                "SELECT roles FROM admin_users WHERE id = %s",
                (user_id,),
            )
            row = cur.fetchone()
    finally:
        conn.close()

    roles = row[0] if row else []

    # 生成新的 access_token,refresh_token 原样返回
    new_access = create_access_token(user_id, site_id, roles=roles or [], audience="admin")
    return TokenResponse(
        access_token=new_access,
        refresh_token=body.refresh_token,
        token_type="bearer",
    )
