from fastapi import Depends, Header, HTTPException, Request, status
from common_logging import get_logger
from sqlalchemy.orm import Session

from app.core.i18n import get_translator
from app.core.security import decode_access_token, is_token_revoked
from app.db.session import get_db_without_tenant
from app.models.tenant import Tenant
from app.models.user import User
from app.services.llm.service_status_manager import ServiceStatusManager, get_status_manager

logger = get_logger(__name__)
get_db = get_db_without_tenant


def get_service_status_manager() -> ServiceStatusManager:
    return get_status_manager()


async def get_current_user(
    request: Request,
    authorization: str | None = Header(None),
    db: Session = Depends(get_db_without_tenant),
) -> User:
    t = get_translator(request)
    if not authorization:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED, detail=t.t("auth.not_authenticated")
        )
    try:
        scheme, token = authorization.split()
        if scheme.lower() != "bearer":
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED, detail=t.t("auth.invalid_auth_scheme")
            )
    except ValueError:
        logger.warning("Invalid authorization header format")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED, detail=t.t("auth.invalid_auth_header")
        ) from None
    payload = decode_access_token(token)
    if not payload:
        logger.warning("Invalid or expired token")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED, detail=t.t("auth.invalid_or_expired_token")
        )
    if is_token_revoked(token):
        logger.warning("Token revoked")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED, detail=t.t("auth.token_revoked")
        )
    user_id = payload.get("sub")
    if not user_id:
        logger.warning("Invalid token payload")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED, detail=t.t("auth.invalid_token_payload")
        )
    from sqlalchemy.orm import joinedload

    from app.models.user_role import UserRole

    user = (
        db.query(User)
        .options(joinedload(User.user_roles).joinedload(UserRole.role))
        .filter(User.id == int(user_id))
        .first()
    )
    if not user:
        logger.warning(f"User not found: id={user_id}")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED, detail=t.t("auth.user_not_found")
        )
    jwt_tenant_id = payload.get("tenant_id")
    if jwt_tenant_id is not None:
        if user.tenant_id != jwt_tenant_id:
            logger.warning(f"Tenant mismatch: user_id={user_id}, jwt_tenant={jwt_tenant_id}, user_tenant={user.tenant_id}")
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN, detail=t.t("auth.tenant_mismatch")
            )
    if not user.is_verified:
        logger.warning(f"Email not verified: user_id={user_id}")
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN, detail=t.t("auth.email_not_verified")
        )
    if not user.is_active:
        logger.warning(f"Account disabled: user_id={user_id}")
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN, detail=t.t("auth.account_disabled")
        )
    return user


def get_current_user_from_token(token: str, db: Session) -> User:
    payload = decode_access_token(token)
    if not payload:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid or expired token"
        )
    if is_token_revoked(token):
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Token revoked")
    user_id = payload.get("sub")
    if not user_id:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token payload"
        )
    from sqlalchemy.orm import joinedload

    from app.models.user_role import UserRole

    user = (
        db.query(User)
        .options(joinedload(User.user_roles).joinedload(UserRole.role))
        .filter(User.id == int(user_id))
        .first()
    )
    if not user:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="User not found")
    if not user.is_verified or not user.is_active:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Account not active")
    return user


async def get_current_tenant(
    request: Request,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db_without_tenant),
) -> Tenant:
    t = get_translator(request)
    if not current_user.tenant_id:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=t.t("auth.no_tenant"))
    tenant = db.query(Tenant).filter(Tenant.id == current_user.tenant_id).first()
    if not tenant:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, detail=t.t("auth.tenant_not_found")
        )
    return tenant
