"""Structured logging configuration using structlog.

Provides structured logging for debugging, auditing, and production use.
Logs are written to stderr in a format suitable for log aggregation systems.

Usage:
    from alice_cli.logging import get_logger

    log = get_logger(__name__)
    log.info("operation_started", operation="invoke", model="sonnet")
    log.error("api_call_failed", exc_info=True, provider="bedrock")
"""

from __future__ import annotations

import logging
import sys
from typing import Any

import structlog


def configure_logging(*, json_logs: bool = False, log_level: str = "INFO") -> None:
    """Configure structlog with appropriate processors and formatting.

    Args:
        json_logs: If True, output JSON format suitable for log aggregation.
                   If False, output human-readable colored logs (development).
        log_level: Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL).
    """
    level = getattr(logging, log_level.upper(), logging.INFO)

    # Configure the standard library logger that structlog wraps
    logging.basicConfig(
        format="%(message)s",
        stream=sys.stderr,
        level=level,
    )

    # Silence verbose third-party SDK loggers that bypass alice-cli's
    # structlog configuration and write directly to the root logger.
    for _noisy in ("bedrock_agentcore", "botocore", "boto3", "urllib3"):
        logging.getLogger(_noisy).setLevel(max(level, logging.WARNING))

    # Choose processors based on output format
    processors: list[Any] = [
        structlog.stdlib.add_log_level,
        structlog.stdlib.add_logger_name,
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.contextvars.merge_contextvars,
        structlog.processors.StackInfoRenderer(),
    ]

    if json_logs:
        # JSON output for production/aggregation
        processors.append(structlog.processors.dict_tracebacks)
        processors.append(structlog.processors.JSONRenderer())
    else:
        # Human-readable colored output for development
        processors.append(structlog.dev.ConsoleRenderer(colors=True))

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


def get_logger(name: str) -> structlog.stdlib.BoundLogger:
    """Get a structlog logger bound to the given name.

    Args:
        name: Logger name (typically __name__ from the calling module).

    Returns:
        A structlog BoundLogger instance.

    Example:
        >>> log = get_logger(__name__)
        >>> log.info("user_authenticated", username="testuser", region="us-east-1")
    """
    return structlog.get_logger(name)  # type: ignore[no-any-return,return-value,unused-ignore]


# Initialize with sensible defaults on module import
# Users can call configure_logging() to override
configure_logging(json_logs=False, log_level="INFO")
