"""
FastAPI dependency for binding domain-specific IDs to loguru context.

Extracts identifiers like agent_session_id, agent_id, task_run_id from
request path/query params and binds them via logger.contextualize() so
every log line emitted during the request automatically includes them.

These IDs are promoted to top-level JSON fields by json_serializer() in
log_config.py, making them queryable in Loki via:
    {service="actx-server"} | json | agent_session_id="abc123"

Usage:
    from common.log_context import create_log_context_dependency
    from fastapi import Depends

    app.router.dependencies.append(Depends(create_log_context_dependency()))
"""

from loguru import logger
from fastapi import Request

_DEFAULT_PARAM_MAP = {
    "agent_session_id": "agent_session_id",
    "session_id": "agent_session_id",  # actx-server uses session_id in routes
    "agent_id": "agent_id",
    "task_run_id": "task_run_id",
    "task_id": "task_id",
    "trigger_id": "trigger_id",
    "user_id": "user_id",
}


def create_log_context_dependency(param_map: dict[str, str] | None = None):
    """Create a FastAPI dependency that binds domain IDs to loguru context.

    Uses a generator dependency (not middleware) so it works correctly with
    SSE streaming endpoints. The logger.contextualize() call uses ContextVar
    under the hood, making it async-safe.

    Args:
        param_map: Optional override/extension of the default parameter mapping.
                   Keys are request param names, values are log context keys.
    """
    mapping = {**_DEFAULT_PARAM_MAP, **(param_map or {})}

    async def _log_context(request: Request):
        ctx = {}
        # First, check path params (higher priority)
        for param_name, log_key in mapping.items():
            val = request.path_params.get(param_name)
            if val:
                ctx[log_key] = val
        # Then, fill in from query params for any keys not yet set
        for param_name, log_key in mapping.items():
            if log_key not in ctx:
                val = request.query_params.get(param_name)
                if val:
                    ctx[log_key] = val
        if ctx:
            with logger.contextualize(**ctx):
                yield
        else:
            yield

    return _log_context
