"""
FastAPI Dependencies

Shared dependencies for API endpoints
"""

from typing import Generator, Optional
from fastapi import Depends, HTTPException, status, Security
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.orm import Session

from config.database import get_db_session
from config.settings import settings
from src.database.models import User


# =============================================================================
# DATABASE DEPENDENCY
# =============================================================================

def get_db() -> Generator[Session, None, None]:
    """
    Database session dependency

    Yields database session and ensures it's closed after request
    """
    session = get_db_session()
    try:
        yield session
    finally:
        session.close()


# =============================================================================
# AUTHENTICATION DEPENDENCIES
# =============================================================================

# HTTP Bearer token scheme
security = HTTPBearer(auto_error=False)


def get_current_user(
    credentials: Optional[HTTPAuthorizationCredentials] = Security(security),
    db: Session = Depends(get_db)
) -> Optional[User]:
    """
    Get current authenticated user from JWT token

    Args:
        credentials: Bearer token from Authorization header
        db: Database session

    Returns:
        User object if authenticated, None if auth not required

    Raises:
        HTTPException: If authentication required but invalid
    """

    # If authentication not required (development mode)
    if not settings.require_auth:
        # Return anonymous user (ID 0)
        return db.query(User).filter_by(id=0).first()

    # Authentication required
    if not credentials:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Authentication required",
            headers={"WWW-Authenticate": "Bearer"},
        )

    try:
        # Decode JWT token (implementation in auth.py)
        from src.api.auth import decode_access_token

        payload = decode_access_token(credentials.credentials)
        user_id = payload.get("sub")

        if user_id is None:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Invalid authentication token"
            )

        # Get user from database
        user = db.query(User).filter_by(id=int(user_id)).first()

        if user is None:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="User not found"
            )

        return user

    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail=f"Authentication failed: {str(e)}"
        )


def require_auth(user: User = Depends(get_current_user)) -> User:
    """
    Require authentication (always)

    Use this dependency when endpoint must have authentication
    regardless of global settings

    Args:
        user: Current user from get_current_user

    Returns:
        Authenticated user

    Raises:
        HTTPException: If user not authenticated
    """
    if user is None or user.id == 0:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Authentication required for this endpoint"
        )

    return user


def optional_auth(user: Optional[User] = Depends(get_current_user)) -> Optional[User]:
    """
    Optional authentication

    Returns user if authenticated, None otherwise (no error)

    Args:
        user: Current user from get_current_user

    Returns:
        User if authenticated, None otherwise
    """
    return user


# =============================================================================
# PAGINATION DEPENDENCIES
# =============================================================================

def get_pagination(
    skip: int = 0,
    limit: int = 100
) -> dict:
    """
    Pagination parameters

    Args:
        skip: Number of records to skip
        limit: Maximum number of records to return

    Returns:
        Dictionary with skip and limit
    """
    # Enforce maximum limit
    max_limit = 1000
    if limit > max_limit:
        limit = max_limit

    return {
        "skip": skip,
        "limit": limit
    }


# =============================================================================
# STORAGE DEPENDENCY
# =============================================================================

def get_storage():
    """
    Get storage backend

    Returns:
        Storage backend instance (LocalStorage or S3Storage)
    """
    from src.core.storage import get_storage
    return get_storage()
