import traceback

from fastapi import Request, status
from fastapi.responses import PlainTextResponse
from fastapi.templating import Jinja2Templates
from jinja2 import PackageLoader, Environment


def custom_exception_handler(request: Request, exc: Exception):
    """
    Custom error handler for unhandled exceptions.

    Uses the app's full template environment (sidebar, globals, SIGNAL design)
    when available. Falls back to a plain-text response if template rendering
    itself fails (e.g. the error occurred inside base.html.j2).
    """
    traceback_str = "".join(traceback.format_exception(type(exc), exc, exc.__traceback__))

    # Only expose the traceback when debug mode is on
    fp = getattr(request.app.state, "fastpluggy", None)
    debug = getattr(getattr(fp, "settings", None), "debug", False)

    templates = getattr(request.app.state, "jinja_templates", None)
    if templates is None:
        templates = Jinja2Templates(env=Environment(loader=PackageLoader("fastpluggy", "templates")))  # nosec B701

    try:
        return templates.TemplateResponse(
            "error.html.j2",
            {
                "request": request,
                "error_message": str(exc),
                "traceback": traceback_str if debug else None,
            },
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        )
    except Exception:
        # Template rendering itself failed — return safe plain text
        body = f"500 Internal Server Error\n\n{exc}"
        if debug:
            body += f"\n\n{traceback_str}"
        return PlainTextResponse(body, status_code=500)
