from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from jose import JWTError, jwt
from sqlalchemy.orm import Session
from typing import Optional
import os
from ..config.database import get_db
from ..config.settings import settings
from ..models.user import User
from ..models.role import Role
security = HTTPBearer()

def get_current_user(credentials: HTTPAuthorizationCredentials=Depends(security), db: Session=Depends(get_db)) -> User:
    token = credentials.credentials
    credentials_exception = HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail='Could not validate credentials', headers={'WWW-Authenticate': 'Bearer'})
    try:
        jwt_secret = getattr(settings, 'JWT_SECRET', None) or os.getenv('JWT_SECRET', 'dev-secret-key-change-in-production-12345')
        payload = jwt.decode(token, jwt_secret, algorithms=['HS256'])
        user_id: int = payload.get('userId')
        if user_id is None:
            raise credentials_exception
    except JWTError:
        raise credentials_exception
    user = db.query(User).filter(User.id == user_id).first()
    if user is None:
        raise credentials_exception
    return user

def authorize_roles(*allowed_roles: str):

    def role_checker(current_user: User=Depends(get_current_user), db: Session=Depends(get_db)) -> User:
        role = db.query(Role).filter(Role.id == current_user.role_id).first()
        if not role:
            raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail='User role not found')
        user_role_name = role.name
        if user_role_name not in allowed_roles:
            raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail='You do not have permission to access this resource')
        return current_user
    return role_checker

def get_current_user_optional(credentials: Optional[HTTPAuthorizationCredentials]=Depends(HTTPBearer(auto_error=False)), db: Session=Depends(get_db)) -> Optional[User]:
    if not credentials:
        return None
    token = credentials.credentials
    try:
        jwt_secret = getattr(settings, 'JWT_SECRET', None) or os.getenv('JWT_SECRET', 'dev-secret-key-change-in-production-12345')
        payload = jwt.decode(token, jwt_secret, algorithms=['HS256'])
        user_id: int = payload.get('userId')
        if user_id is None:
            return None
    except JWTError:
        return None
    user = db.query(User).filter(User.id == user_id).first()
    return user

def verify_token(token: str) -> dict:
    jwt_secret = getattr(settings, 'JWT_SECRET', None) or os.getenv('JWT_SECRET', 'dev-secret-key-change-in-production-12345')
    payload = jwt.decode(token, jwt_secret, algorithms=['HS256'])
    return payload