"""Cookie-based JWT authentication middleware.

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

from __future__ import annotations

import logging
from typing import Annotated

import jwt
from fastapi import Cookie, Depends, HTTPException, status
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

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

logger = logging.getLogger(__name__)

SESSION_COOKIE_NAME = auth_settings.session_cookie_name


async def get_session_token(
    session_token: str | None = Cookie(
        None,
        alias=SESSION_COOKIE_NAME,
    ),
) -> str:
    """Extract session token from cookie.

    Args:
        session_token: Session cookie value

    Returns:
        Session token string

    Raises:
        HTTPException: If no session token is present (401)
    """
    if not session_token:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Not authenticated",
            headers={"WWW-Authenticate": "Bearer"},
        )
    return session_token


async def get_current_user(
    session_token: Annotated[str, Depends(get_session_token)],
    db: Annotated[AsyncSession, Depends(get_db)],
) -> {{ user_model }}:
    """Get current authenticated user from cookie-based JWT session.

    Args:
        session_token: JWT session token from cookie
        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:
        claims = decode_session_jwt(session_token)
        user_id = claims.get("sub")
        if not user_id:
            raise credentials_exception
    except jwt.InvalidTokenError:
        raise credentials_exception from None

    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="User account is inactive",
        )
    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 or [])

        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 in route definitions
CurrentUser = Annotated[{{ user_model }}, Depends(get_current_user)]
CurrentActiveUser = Annotated[{{ user_model }}, Depends(get_current_active_user)]
