"""
InsAIts SDK - Structured Logger
================================
JSON-formatted structured logging with correlation IDs for
distributed tracing across multi-agent systems.

Named structured_logging.py to avoid shadowing Python's stdlib logging module.

All log entries are machine-parseable JSON with:
    - ISO timestamp
    - Severity level
    - Event type
    - Correlation ID for request tracing
    - Arbitrary key-value metadata
"""

import json
import logging
import time
from datetime import datetime, timezone
from typing import Any, Dict, Optional


logger = logging.getLogger(__name__)


class StructuredLogger:
    """JSON structured logger for InsAIts events.

    Emits machine-parseable JSON log lines through the standard
    logging framework. Supports correlation IDs for distributed
    request tracing across agent pipelines.

    Usage:
        slog = StructuredLogger()
        slog.anomaly_detected("SEMANTIC_DRIFT", "high", "agent1", "agent2", "corr-123")
        slog.message_clean("agent1", "agent2", "corr-123")
    """

    def __init__(
        self,
        name: str = "insaits",
        level: str = "INFO",
    ):
        """Initialize the structured logger.

        Args:
            name: Logger name for filtering
            level: Minimum log level (DEBUG, INFO, WARNING, ERROR)
        """
        self._logger = logging.getLogger(name)
        numeric_level = getattr(logging, level.upper(), logging.INFO)
        if not self._logger.handlers:
            self._logger.setLevel(numeric_level)

    def _log(
        self,
        level: int,
        event: str,
        correlation_id: Optional[str] = None,
        **kwargs: Any,
    ) -> Dict[str, Any]:
        """Emit a structured log entry.

        Args:
            level: Logging level constant (logging.INFO, etc.)
            event: Event type identifier
            correlation_id: Optional trace ID for distributed tracing
            **kwargs: Additional key-value pairs to include

        Returns:
            The log payload dict (for testing/inspection)
        """
        payload: Dict[str, Any] = {
            "ts": datetime.now(timezone.utc).isoformat(),
            "event": event,
        }

        if correlation_id is not None:
            payload["correlation_id"] = correlation_id

        payload.update(kwargs)

        # Emit through standard logging as JSON
        self._logger.log(level, json.dumps(payload, default=str))
        return payload

    # -- Convenience methods for common events --

    def anomaly_detected(
        self,
        anomaly_type: str,
        severity: str,
        sender: str,
        receiver: str,
        correlation_id: Optional[str] = None,
        **kwargs: Any,
    ) -> Dict[str, Any]:
        """Log an anomaly detection event.

        Args:
            anomaly_type: e.g. "SEMANTIC_DRIFT", "HALLUCINATION_CHAIN"
            severity: e.g. "low", "medium", "high", "critical"
            sender: Agent that sent the message
            receiver: Agent that receives the message
            correlation_id: Optional trace ID
        """
        level = logging.WARNING if severity in ("high", "critical") else logging.INFO
        return self._log(
            level,
            "anomaly.detected",
            correlation_id=correlation_id,
            anomaly_type=anomaly_type,
            severity=severity,
            sender=sender,
            receiver=receiver,
            **kwargs,
        )

    def message_clean(
        self,
        sender: str,
        receiver: str,
        correlation_id: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Log a clean message (no anomalies)."""
        return self._log(
            logging.DEBUG,
            "message.clean",
            correlation_id=correlation_id,
            sender=sender,
            receiver=receiver,
        )

    def readiness_check(
        self,
        ready: bool,
        checks: Dict[str, Any],
    ) -> Dict[str, Any]:
        """Log a readiness check result."""
        level = logging.INFO if ready else logging.WARNING
        summary = {
            name: check.get("status", "unknown")
            for name, check in checks.items()
        }
        return self._log(
            level,
            "readiness.check",
            ready=ready,
            summary=summary,
        )

    def circuit_breaker_tripped(
        self,
        agent_id: str,
        anomaly_rate: float,
        correlation_id: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Log a circuit breaker state change."""
        return self._log(
            logging.WARNING,
            "circuit_breaker.open",
            correlation_id=correlation_id,
            agent_id=agent_id,
            anomaly_rate=round(anomaly_rate, 3),
        )

    def intervention_triggered(
        self,
        action: str,
        sender: str,
        severity: str,
        correlation_id: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Log an intervention action."""
        return self._log(
            logging.WARNING,
            "intervention.triggered",
            correlation_id=correlation_id,
            action=action,
            sender=sender,
            severity=severity,
        )
