"""JWT authentication middleware.

⚠️ AUTO-GENERATED BY PRISM - DO NOT EDIT
FastAPI dependencies for authentication and authorization.
"""

from __future__ import annotations

from typing import Annotated

from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from {{ project_name }}.auth.token_service import token_service
from {{ project_name }}.database import get_db
from {{ project_name }}.models.{{ user_model_snake }} import {{ user_model }}

security = HTTPBearer()


async def get_current_user(
    credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)],
    db: Annotated[AsyncSession, Depends(get_db)],
) -> {{ user_model }}:
    """Get current authenticated user from JWT token.

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

    Returns:
        Authenticated user object

    Raises:
        HTTPException: If token is invalid or user not found (401)
    """
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )

    try:
        token = credentials.credentials
        payload = token_service.verify_token(token, token_type="access")
        user_id: str | None = payload.get("sub")

        if user_id is None:
            raise credentials_exception
    except Exception:
        raise credentials_exception

    # Fetch user from database
    result = await db.execute(select({{ user_model }}).where({{ user_model }}.id == int(user_id)))
    user = result.scalar_one_or_none()

    if user is None:
        raise credentials_exception

    return user


async def get_current_active_user(
    current_user: Annotated[{{ user_model }}, Depends(get_current_user)],
) -> {{ user_model }}:
    """Get current active user (checks is_active flag).

    Args:
        current_user: User from get_current_user dependency

    Returns:
        Active user object

    Raises:
        HTTPException: If user is inactive (403)
    """
    if not current_user.is_active:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Inactive user")
    return current_user


def require_roles(*required_roles: str):
    """Dependency factory for role-based access control.

    Usage:
        @router.get("/admin", dependencies=[Depends(require_roles("admin"))])

    Args:
        *required_roles: One or more role names required for access

    Returns:
        FastAPI dependency function that checks user roles
    """

    async def check_roles(
        current_user: Annotated[{{ user_model }}, Depends(get_current_active_user)],
    ) -> {{ user_model }}:
        """Check if user has required roles."""
        user_roles = set(current_user.roles)

        # Check for wildcard or matching role
        if "*" in required_roles or any(role in user_roles for role in required_roles):
            return current_user

        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail=f"Required roles: {', '.join(required_roles)}",
        )

    return check_roles


# Type aliases for convenience
CurrentUser = Annotated[{{ user_model }}, Depends(get_current_user)]
CurrentActiveUser = Annotated[{{ user_model }}, Depends(get_current_active_user)]
