"""
Metrics and monitoring integration for Python SDK
"""

from typing import Dict, List, Optional, Any
from dataclasses import dataclass, field
from datetime import datetime
import time


@dataclass
class Metric:
    name: str
    value: float
    timestamp: float
    tags: Dict[str, str] = field(default_factory=dict)


class MetricsCollector:
    """Metrics collector for Aegis SDK"""

    def __init__(
        self,
        enabled: bool = True,
        flush_interval: int = 60,
        endpoint: str = "/metrics",
    ):
        self.enabled = enabled
        self.flush_interval = flush_interval
        self.endpoint = endpoint
        
        self.metrics: List[Metric] = []
        self.counters: Dict[str, float] = {}
        self.gauges: Dict[str, float] = {}
        self.histograms: Dict[str, List[float]] = {}

    def increment_counter(
        self, name: str, value: float = 1.0, tags: Optional[Dict[str, str]] = None
    ):
        """Increment counter"""
        if not self.enabled:
            return

        current = self.counters.get(name, 0)
        self.counters[name] = current + value

        self._record_metric(
            Metric(
                name=f"{name}.count",
                value=value,
                timestamp=time.time(),
                tags=tags or {},
            )
        )

    def set_gauge(self, name: str, value: float, tags: Optional[Dict[str, str]] = None):
        """Set gauge value"""
        if not self.enabled:
            return

        self.gauges[name] = value

        self._record_metric(
            Metric(
                name=f"{name}.gauge",
                value=value,
                timestamp=time.time(),
                tags=tags or {},
            )
        )

    def record_histogram(
        self, name: str, value: float, tags: Optional[Dict[str, str]] = None
    ):
        """Record histogram value"""
        if not self.enabled:
            return

        if name not in self.histograms:
            self.histograms[name] = []
        self.histograms[name].append(value)

        self._record_metric(
            Metric(
                name=f"{name}.histogram",
                value=value,
                timestamp=time.time(),
                tags=tags or {},
            )
        )

    def record_timing(
        self, name: str, duration_ms: float, tags: Optional[Dict[str, str]] = None
    ):
        """Record timing"""
        self.record_histogram(f"{name}.duration", duration_ms, tags)

    def get_counter(self, name: str) -> float:
        """Get counter value"""
        return self.counters.get(name, 0)

    def get_gauge(self, name: str) -> float:
        """Get gauge value"""
        return self.gauges.get(name, 0)

    def get_histogram_stats(self, name: str) -> Optional[Dict[str, float]]:
        """Get histogram statistics"""
        values = self.histograms.get(name)
        if not values:
            return None

        sorted_values = sorted(values)
        count = len(sorted_values)

        return {
            "min": sorted_values[0],
            "max": sorted_values[-1],
            "avg": sum(sorted_values) / count,
            "p50": sorted_values[int(count * 0.5)],
            "p95": sorted_values[int(count * 0.95)],
            "p99": sorted_values[int(count * 0.99)],
        }

    def _record_metric(self, metric: Metric):
        """Record metric"""
        self.metrics.append(metric)

    async def flush(self):
        """Flush metrics"""
        if not self.metrics:
            return

        metrics_to_flush = self.metrics[:]
        self.metrics = []

        print(f"[Metrics] Flushing {len(metrics_to_flush)} metrics")

    def get_all_metrics(self) -> List[Metric]:
        """Get all metrics"""
        return self.metrics[:]

    def clear(self):
        """Clear all metrics"""
        self.metrics = []
        self.counters = {}
        self.gauges = {}
        self.histograms = {}


class AegisMetrics:
    """Pre-configured metrics for Aegis operations"""

    def __init__(self, collector: MetricsCollector):
        self.collector = collector

    def record_tool_call_validation(
        self, allowed: bool, capability: str, duration_ms: float
    ):
        """Record tool call validation"""
        self.collector.increment_counter(
            "tool_call.validation",
            1,
            {"allowed": str(allowed), "capability": capability},
        )
        self.collector.record_timing(
            "tool_call.validation", duration_ms, {"capability": capability}
        )

    def record_approval_request(self, capability: str):
        """Record approval request"""
        self.collector.increment_counter(
            "approval.request", 1, {"capability": capability}
        )

    def record_approval_decision(self, approved: bool, capability: str):
        """Record approval decision"""
        self.collector.increment_counter(
            "approval.decision",
            1,
            {"approved": str(approved), "capability": capability},
        )

    def record_policy_evaluation(self, result: str, duration_ms: float):
        """Record policy evaluation"""
        self.collector.increment_counter("policy.evaluation", 1, {"result": result})
        self.collector.record_timing("policy.evaluation", duration_ms)

    def record_taint_check(self, blocked: bool, duration_ms: float):
        """Record taint check"""
        self.collector.increment_counter(
            "taint.check", 1, {"blocked": str(blocked)}
        )
        self.collector.record_timing("taint.check", duration_ms)

    def record_api_call(self, endpoint: str, status_code: int, duration_ms: float):
        """Record API call"""
        self.collector.increment_counter(
            "api.call", 1, {"endpoint": endpoint, "status": str(status_code)}
        )
        self.collector.record_timing("api.call", duration_ms, {"endpoint": endpoint})

    def record_error(self, error_type: str, endpoint: str = "unknown"):
        """Record error"""
        self.collector.increment_counter(
            "error", 1, {"type": error_type, "endpoint": endpoint}
        )
