# app/api/dependencies.py
import logging
from typing import Optional

from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from sqlalchemy.ext.asyncio import AsyncSession
from jose import JWTError

from app.database import get_db
from app.core.security import verify_access_token
from app.crud import user as crud_user
from app.models import User as UserModel # Import the SQLAlchemy model

logger = logging.getLogger(__name__)

# Define the OAuth2 scheme
# tokenUrl should point to your login endpoint relative to the base path
# It's used by Swagger UI for the "Authorize" button flow.
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login") # Corrected path

async def get_current_user(
    token: str = Depends(oauth2_scheme),
    db: AsyncSession = Depends(get_db)
) -> UserModel:
    """
    Dependency to get the current user based on the JWT token.

    - Extracts token using OAuth2PasswordBearer.
    - Verifies the token (signature, expiry).
    - Fetches the user from the database based on the token's subject (email).
    - Raises HTTPException 401 if any step fails.

    Returns:
        The authenticated user's database model instance.
    """
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )

    payload = verify_access_token(token)
    if payload is None:
        logger.warning("Token verification failed (invalid, expired, or malformed).")
        raise credentials_exception

    email: Optional[str] = payload.get("sub")
    if email is None:
        logger.error("Token payload missing 'sub' (subject/email).")
        raise credentials_exception # Token is malformed

    # Fetch user from database
    user = await crud_user.get_user_by_email(db, email=email)
    if user is None:
        logger.warning(f"User corresponding to token subject not found: {email}")
        # Could happen if user deleted after token issuance
        raise credentials_exception # Treat as invalid credentials

    logger.debug(f"Authenticated user retrieved: {user.email} (ID: {user.id})")
    return user

# Optional: Dependency for getting the *active* current user
# You might add an `is_active` flag to your User model later
# async def get_current_active_user(
#     current_user: UserModel = Depends(get_current_user)
# ) -> UserModel:
#     if not current_user.is_active: # Assuming an is_active attribute
#          logger.warning(f"Authentication attempt by inactive user: {current_user.email}")
#          raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Inactive user")
#     return current_user