import traceback

from fastapi import HTTPException, Request
from fastapi.responses import JSONResponse
from sqlalchemy.exc import ProgrammingError
from sqlalchemy.exc import OperationalError

from app.log import get_logger
from app.utils.log_utils import CUSTOM_LOGGER

log = get_logger(__name__)


class CustomHttpException(HTTPException):
    """Custom HTTP Exception class to handle exceptions with custom messages."""

    def __init__(self, status_code: int, detail: str, headers: dict | None = None) -> None:
        super().__init__(status_code=status_code, detail=detail, headers=headers)


class SessionException(HTTPException):
    """Session expired exception."""

    def __init__(self, status_code: int = 401, detail: str = "Session expired", headers: dict | None = None) -> None:
        super().__init__(status_code=status_code, detail=detail, headers=headers)


def log_error(request: Request, exc: Exception) -> None:
    """Log the error message."""
    url_path = request.url.path
    error_message = f"[Error] {url_path}: {exc}"
    error_traceback = traceback.format_exc()  # Get the traceback information as a string
    full_error_message = f"{error_message}\n{error_traceback}"  # Combine error message and traceback
    log.error(error_message)
    CUSTOM_LOGGER.error_log(error_message)
    if not isinstance(exc, HTTPException):
        log.error(full_error_message)
        CUSTOM_LOGGER.stack_trace(error_traceback)



def http_exception_error_handler(request: Request, exc: HTTPException) -> JSONResponse:
    """HTTP Exception handler to return custom messages."""
    headers = exc.headers
    log_error(request, exc)
    return JSONResponse(status_code=200, content={"status": "-1", "message": exc.detail}, headers=headers)



async def handle_programming_error(request: Request, exc: ProgrammingError) -> JSONResponse:
    """Handle ProgrammingError exception."""
    error_message = str(exc)
    log_error(request, exc)
    if "Table" in error_message and "doesn't exist" in error_message:
        return JSONResponse(
            status_code=200,
            content={"status": "-1", "message": "Requested resource not found", "error": error_message},
        )
    return JSONResponse(
        status_code=200,
        content={"status": "-1", "message": "Internal server error", "error": error_message},
    )


async def handle_generic_exception_handler(request: Request, exc: Exception) -> JSONResponse:
    """Handle generic exception."""
    log_error(request, exc)
    return JSONResponse(
        status_code=200,
        content={"status": "-1", "message": "An error occurred", "error": str(exc)},
    )


async def handel_operational_error_handler(request: Request, exc: OperationalError) -> HTTPException:
    """Handle OperationalError exception."""
    error_message = str(exc)
    log_error(request, exc)
    return HTTPException(status_code=500, detail=error_message)
    
async def handel_attribute_error_handler(request: Request, exc: AttributeError) -> HTTPException:
    """Handle AttributeError exception."""
    error_message = str(exc)
    log_error(request, exc)
    return HTTPException(status_code=500, detail=error_message)