from fastapi import Request, FastAPI
from fastapi.responses import JSONResponse
from app.core.logging_config import logger

class BaseAppException(Exception):
    """Custom base exception for handling domain and application level errors."""
    def __init__(self, message: str, status_code: int = 400, code: str = "BAD_REQUEST"):
        super().__init__(message)
        self.message = message
        self.status_code = status_code
        self.code = code

class NotFoundException(BaseAppException):
    def __init__(self, message: str = "Resource not found"):
        super().__init__(message, status_code=404, code="NOT_FOUND")

class BadRequestException(BaseAppException):
    def __init__(self, message: str = "Bad request"):
        super().__init__(message, status_code=400, code="BAD_REQUEST")

class UnauthorizedException(BaseAppException):
    def __init__(self, message: str = "Could not validate credentials"):
        super().__init__(message, status_code=401, code="UNAUTHORIZED")

class ForbiddenException(BaseAppException):
    def __init__(self, message: str = "Access forbidden"):
        super().__init__(message, status_code=403, code="FORBIDDEN")

def register_exception_handlers(app: FastAPI):
    """Global exception handler registration for uniform JSON responses."""
    @app.exception_handler(BaseAppException)
    async def custom_app_exception_handler(request: Request, exc: BaseAppException):
        logger.error(f"App error occurred: {exc.code} - {exc.message}")
        return JSONResponse(
            status_code=exc.status_code,
            content={
                "success": False,
                "error": {
                    "code": exc.code,
                    "message": exc.message
                }
            }
        )

    @app.exception_handler(Exception)
    async def global_exception_handler(request: Request, exc: Exception):
        logger.exception("An unhandled system error occurred.")
        return JSONResponse(
            status_code=500,
            content={
                "success": False,
                "error": {
                    "code": "INTERNAL_SERVER_ERROR",
                    "message": "Internal Server Error. Please contact admin."
                }
            }
        )
