"""
认证API路由示例代码
"""
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
from sqlalchemy.ext.asyncio import AsyncSession

from app.api.deps import get_db
from app.core.exceptions import UnauthorizedError, ConflictError
from app.schemas.auth import UserRegister, Token, PasswordReset
from app.schemas.base import ResponseModel
from app.services.auth_service import AuthService

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


@router.post("/login", response_model=ResponseModel[Token], summary="用户登录")
async def login(
    form_data: OAuth2PasswordRequestForm = Depends(),
    db: AsyncSession = Depends(get_db)
):
    """
    用户登录接口
    
    - **username**: 用户名或邮箱
    - **password**: 密码
    
    返回访问令牌和刷新令牌
    """
    auth_service = AuthService(db)
    
    # 验证用户
    user = await auth_service.authenticate_user(
        username=form_data.username,
        password=form_data.password
    )
    
    if not user:
        raise UnauthorizedError("用户名或密码错误")
    
    # 创建Token
    token = await auth_service.create_tokens(user)
    
    return ResponseModel(
        code=200,
        message="登录成功",
        data=token
    )


@router.post("/register", response_model=ResponseModel[Token], status_code=status.HTTP_201_CREATED)
async def register(
    user_data: UserRegister,
    db: AsyncSession = Depends(get_db)
):
    """
    用户注册接口
    
    注册成功后自动登录，返回Token
    """
    # 验证密码一致性
    if user_data.password != user_data.confirm_password:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="两次输入的密码不一致"
        )
    
    auth_service = AuthService(db)
    
    try:
        # 创建用户
        user = await auth_service.create_user(user_data)
        
        # 自动登录
        token = await auth_service.create_tokens(user)
        
        return ResponseModel(
            code=201,
            message="注册成功",
            data=token
        )
    except ConflictError as e:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail=str(e)
        )


@router.post("/logout", response_model=ResponseModel)
async def logout(
    token: str = Depends(get_current_token),
    db: AsyncSession = Depends(get_db)
):
    """
    用户登出接口
    
    将当前Token加入黑名单
    """
    auth_service = AuthService(db)
    await auth_service.logout(token)
    
    return ResponseModel(
        code=200,
        message="登出成功"
    )


@router.post("/refresh", response_model=ResponseModel[Token])
async def refresh_token(
    refresh_token: str,
    db: AsyncSession = Depends(get_db)
):
    """
    刷新访问令牌
    
    使用刷新令牌获取新的访问令牌
    """
    auth_service = AuthService(db)
    
    try:
        token = await auth_service.refresh_access_token(refresh_token)
        return ResponseModel(
            code=200,
            message="刷新成功",
            data=token
        )
    except UnauthorizedError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="刷新令牌无效或已过期"
        )


@router.post("/reset-password/request", response_model=ResponseModel)
async def request_password_reset(
    email: str,
    db: AsyncSession = Depends(get_db)
):
    """
    请求重置密码
    
    向用户邮箱发送重置链接
    """
    auth_service = AuthService(db)
    
    # 查找用户
    user = await auth_service.get_user_by_email(email)
    if not user:
        # 为了安全，即使用户不存在也返回成功
        return ResponseModel(
            code=200,
            message="如果邮箱存在，重置链接已发送"
        )
    
    # 生成重置令牌
    reset_token = await auth_service.create_password_reset_token(user)
    
    # TODO: 发送邮件
    # await send_reset_email(email, reset_token)
    
    return ResponseModel(
        code=200,
        message="如果邮箱存在，重置链接已发送"
    )


@router.post("/reset-password/confirm", response_model=ResponseModel)
async def reset_password(
    reset_data: PasswordReset,
    db: AsyncSession = Depends(get_db)
):
    """
    确认重置密码
    
    使用重置令牌设置新密码
    """
    auth_service = AuthService(db)
    
    try:
        await auth_service.reset_password(
            token=reset_data.token,
            new_password=reset_data.new_password
        )
        
        return ResponseModel(
            code=200,
            message="密码重置成功"
        )
    except UnauthorizedError:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="重置令牌无效或已过期"
        )


# 辅助函数
async def get_current_token(
    authorization: str = Depends(oauth2_scheme)
) -> str:
    """获取当前请求的Token"""
    return authorization
