"""Structured logging setup with correlation IDs."""

from __future__ import annotations

from typing import Any

import structlog


def setup_logging(
    *,
    level: str = "INFO",
    json_output: bool = False,
    run_id: str = "",
    thread_id: str = "",
) -> None:
    """Configure structlog for KOAN with optional correlation ID binding.

    Args:
        level: Log level (DEBUG, INFO, WARNING, ERROR).
        json_output: If True, output JSON lines instead of human-readable.
        run_id: Default run_id bound to all log entries.
        thread_id: Default thread_id bound to all log entries.

    Usage::

        setup_logging(level="DEBUG", run_id="r-123", thread_id="t-456")
        log = structlog.get_logger()
        log.info("agent.started", agent="researcher")
    """
    processors: list[Any] = [
        structlog.contextvars.merge_contextvars,
        structlog.stdlib.add_log_level,
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.processors.StackInfoRenderer(),
        structlog.processors.format_exc_info,
    ]

    if json_output:
        processors.append(structlog.processors.JSONRenderer())
    else:
        processors.append(structlog.dev.ConsoleRenderer())

    structlog.configure(
        processors=processors,
        wrapper_class=structlog.stdlib.BoundLogger,
        context_class=dict,
        logger_factory=structlog.PrintLoggerFactory(),
        cache_logger_on_first_use=True,
    )

    # Bind default context vars if provided
    if run_id:
        structlog.contextvars.bind_contextvars(run_id=run_id)
    if thread_id:
        structlog.contextvars.bind_contextvars(thread_id=thread_id)


def bind_context(**kwargs: Any) -> None:
    """Bind key-value pairs to the structlog context for all subsequent logs.

    Usage::

        bind_context(run_id="r-123", agent="researcher")
        log.info("something")  # Will include run_id and agent
    """
    structlog.contextvars.bind_contextvars(**kwargs)


def clear_context() -> None:
    """Clear all bound context variables."""
    structlog.contextvars.clear_contextvars()
