"""Logging configuration using AWS Lambda Powertools.

This module provides standardized logging setup for all handlers,
with structured logging, correlation IDs, and environment integration.

Usage:
    from agent_factory.observability import get_logger

    logger = get_logger(__name__)
    logger.info("Processing request", extra={"user_id": "123"})

For non-Lambda environments or when Powertools is not available,
falls back to standard Python logging.
"""

import logging
import os
from functools import lru_cache
from typing import Any, Optional

# Try to import Powertools, fall back to standard logging
try:
    from aws_lambda_powertools import Logger as PowertoolsLogger

    HAS_POWERTOOLS = True
except ImportError:
    HAS_POWERTOOLS = False
    PowertoolsLogger = None


@lru_cache(maxsize=32)
def get_logger(
    service: Optional[str] = None,
    *,
    child: bool = False,
) -> Any:
    """Get a configured logger instance.

    Uses AWS Lambda Powertools Logger when available for structured logging,
    correlation IDs, and CloudWatch integration. Falls back to standard
    Python logging otherwise.

    Args:
        service: Service/module name for the logger
        child: If True, create a child logger (Powertools only)

    Returns:
        Logger instance (Powertools or standard)

    Example:
        logger = get_logger("my_module")
        logger.info("Hello", extra={"custom": "data"})
    """
    log_level = os.getenv("LOG_LEVEL", os.getenv("POWERTOOLS_LOG_LEVEL", "INFO"))
    service_name = service or os.getenv("POWERTOOLS_SERVICE_NAME", "agent")

    if HAS_POWERTOOLS:
        if child and service:
            # Create child logger with existing root logger
            root_logger = PowertoolsLogger(
                service=service_name,
                level=log_level,
            )
            return root_logger.getChild(service)

        return PowertoolsLogger(
            service=service_name,
            level=log_level,
        )
    else:
        # Fallback to standard logging
        logger = logging.getLogger(service_name)
        logger.setLevel(getattr(logging, log_level.upper(), logging.INFO))

        if not logger.handlers:
            handler = logging.StreamHandler()
            handler.setFormatter(
                logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
            )
            logger.addHandler(handler)

        return logger


def log_handler_start(
    logger: Any,
    handler_name: str,
    event: dict,
    *,
    log_event: bool = False,
) -> None:
    """Log handler invocation start.

    Args:
        logger: Logger instance
        handler_name: Name of the handler
        event: Lambda event
        log_event: If True, log the full event (careful with sensitive data)
    """
    extra = {"handler": handler_name}
    if log_event:
        extra["event"] = event

    logger.info(f"Handler {handler_name} invoked", extra=extra)


def log_handler_complete(
    logger: Any,
    handler_name: str,
    *,
    status_code: int = 200,
    duration_ms: Optional[float] = None,
) -> None:
    """Log handler completion.

    Args:
        logger: Logger instance
        handler_name: Name of the handler
        status_code: HTTP response status code
        duration_ms: Handler duration in milliseconds
    """
    extra: dict[str, Any] = {
        "handler": handler_name,
        "status_code": status_code,
    }
    if duration_ms is not None:
        extra["duration_ms"] = duration_ms

    logger.info(f"Handler {handler_name} completed", extra=extra)


def log_error(
    logger: Any,
    message: str,
    error: Exception,
    *,
    extra: Optional[dict] = None,
) -> None:
    """Log an error with exception details.

    Args:
        logger: Logger instance
        message: Error message
        error: Exception that occurred
        extra: Additional context
    """
    log_extra: dict[str, Any] = {
        "error_type": type(error).__name__,
        "error_message": str(error),
        **(extra or {}),
    }

    if HAS_POWERTOOLS:
        logger.exception(message, extra=log_extra)
    else:
        logger.exception(message, exc_info=error, extra=log_extra)
