from typing import Optional

try:
    from prometheus_client import Counter, Histogram, CollectorRegistry, REGISTRY
except ImportError:
    Counter = None
    Histogram = None
    CollectorRegistry = None
    REGISTRY = None

# Global metrics instance to avoid duplicate registration
_metrics_instance: Optional["MetricsCollector"] = None


class MetricsCollector:
    """Collects Prometheus metrics for rate limiting."""

    def __init__(self, registry: Optional[CollectorRegistry] = None):
        """
        Initialize metrics collector.
        
        Args:
            registry: Optional Prometheus registry. If None, uses default registry.
                     Use a custom registry in tests to avoid conflicts.
        """
        if Counter is None or Histogram is None:
            raise ImportError("prometheus_client not installed")

        self.registry = registry or REGISTRY

        self.requests_total = Counter(
            "rate_limiter_requests_total",
            "Total rate limiter requests",
            ["rule_key", "status"],
            registry=self.registry,
        )

        self.requests_allowed = Counter(
            "rate_limiter_requests_allowed",
            "Allowed rate limiter requests",
            ["rule_key"],
            registry=self.registry,
        )

        self.requests_blocked = Counter(
            "rate_limiter_requests_blocked",
            "Blocked rate limiter requests",
            ["rule_key"],
            registry=self.registry,
        )

        self.request_duration = Histogram(
            "rate_limiter_request_duration_seconds",
            "Rate limiter request duration",
            ["rule_key"],
            registry=self.registry,
        )

    def record_request(self, rule_key: str, allowed: bool) -> None:
        """
        Record a rate limit check.

        Args:
            rule_key: Rule key identifier
            allowed: Whether request was allowed
        """
        status = "allowed" if allowed else "blocked"
        self.requests_total.labels(rule_key=rule_key, status=status).inc()

        if allowed:
            self.requests_allowed.labels(rule_key=rule_key).inc()
        else:
            self.requests_blocked.labels(rule_key=rule_key).inc()


def get_metrics_collector(registry: Optional[CollectorRegistry] = None) -> MetricsCollector:
    """
    Get or create a metrics collector instance.
    
    Uses singleton pattern with default registry to avoid duplicates.
    For tests, pass a custom registry.
    
    Args:
        registry: Optional custom registry (useful for tests)
        
    Returns:
        MetricsCollector instance
    """
    global _metrics_instance
    
    if registry is None:
        # Use singleton for default registry
        if _metrics_instance is None:
            _metrics_instance = MetricsCollector()
        return _metrics_instance
    else:
        # Create new instance for custom registry
        return MetricsCollector(registry=registry)
