"""
认证装饰器
实现滑动过期机制的通用装饰器
"""
import sys
import os

# 添加src目录到Python路径
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../..'))
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../../..'))

from functools import wraps
from fastapi import Depends, HTTPException, Request, Response
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.ext.asyncio import AsyncSession
from app.services.auth_service import AuthService
from app.base.async_mysql_connection import get_db
from app.core.exceptions import AuthenticationError
from app.schemas.base import ApiResponse
from datetime import datetime, timezone
import logging

logger = logging.getLogger(__name__)
security = HTTPBearer()


async def get_current_user_with_sliding_expiration(
    credentials: HTTPAuthorizationCredentials = Depends(security),
    db: AsyncSession = Depends(get_db)
):
    """
    依赖注入函数：获取当前用户并支持滑动过期机制
    
    Returns:
        dict: {"user": User对象, "new_token": str或None}
    """
    try:
        auth_service = AuthService(db)
        user, new_token = await auth_service.get_current_user(credentials.credentials)
        
        if not user:
            raise HTTPException(status_code=401, detail="无效的访问令牌")
        
        return {
            "user": user,
            "new_token": new_token
        }
        
    except AuthenticationError as e:
        raise HTTPException(status_code=e.code, detail=e.message)
    except Exception as e:
        logger.error(f"获取用户信息错误: {e}")
        raise HTTPException(status_code=500, detail="服务器内部错误")


def require_auth_with_sliding_expiration(func):
    """
    需要认证的装饰器，支持滑动过期机制
    
    注意：由于FastAPI的限制，这个装饰器不能直接用于路由函数
    建议使用 get_current_user_with_sliding_expiration 依赖注入
    """
    @wraps(func)
    async def wrapper(*args, **kwargs):
        # 这个装饰器现在主要用于非FastAPI路由的函数
        return await func(*args, **kwargs)
    
    return wrapper


def get_user_from_token(credentials: HTTPAuthorizationCredentials = Depends(security)):
    """
    依赖注入函数：从token获取用户信息（支持滑动过期）
    
    使用方法:
    async def my_api(user_info: dict = Depends(get_user_from_token)):
        user = user_info["user"]
        new_token = user_info["new_token"]  # 可能为None
    """
    async def _get_user(db: AsyncSession = Depends(get_db)):
        try:
            auth_service = AuthService(db)
            user, new_token = await auth_service.get_current_user(credentials.credentials)
            
            if not user:
                raise HTTPException(status_code=401, detail="无效的访问令牌")
            
            return {
                "user": user,
                "new_token": new_token
            }
            
        except AuthenticationError as e:
            raise HTTPException(status_code=e.code, detail=e.message)
        except Exception as e:
            logger.error(f"获取用户信息错误: {e}")
            raise HTTPException(status_code=500, detail="服务器内部错误")
    
    return _get_user