# monitoring/intelligence_metrics.py
import time
import json
import redis
from functools import wraps
from typing import Dict, Any
import logging

log = logging.getLogger(__name__)


class IntelligenceMetricsTracker:
    """Track and analyze intelligence pipeline performance"""

    def __init__(self, redis_url: str = "redis://localhost:6379"):
        self.redis_conn = redis.from_url(redis_url)
        self.metrics_key = "intelligence_metrics"
        self.max_metrics = 1000

    def track_configuration_request(
        self,
        job_id: str,
        duration_ms: float,
        result: Dict[str, Any],
        success: bool = True,
    ):
        """Track a configuration suggestion request"""

        config = result.get("configuration", {}) if success else {}

        metric = {
            "timestamp": time.time(),
            "job_id": job_id,
            "duration_ms": duration_ms,
            "success": success,
            "mappings_found": len(config.get("mappings", [])),
            "confidence": config.get("confidence", 0),
            "blocking_quality": config.get("blocking_strategy", {}).get(
                "quality_score", 0
            ),
            "id_columns_detected": bool(config.get("source_id_column")),
            "ml_models_used": bool(config.get("ml_models_used", {})),
            "error": result.get("error") if not success else None,
        }

        # Store in Redis
        self.redis_conn.lpush(self.metrics_key, json.dumps(metric))
        self.redis_conn.ltrim(self.metrics_key, 0, self.max_metrics - 1)

        # Log for debugging
        if success:
            log.info(
                f"Intelligence pipeline succeeded for {job_id}: "
                f"{metric['mappings_found']} mappings in {duration_ms:.1f}ms"
            )
        else:
            log.error(
                f"Intelligence pipeline failed for {job_id}: {metric.get('error')}"
            )

    def get_metrics_summary(self, last_n: int = 100) -> Dict[str, Any]:
        """Get summary statistics of recent metrics"""

        # Fetch recent metrics
        raw_metrics = self.redis_conn.lrange(self.metrics_key, 0, last_n - 1)
        if not raw_metrics:
            return {"message": "No metrics available yet"}

        metrics = [json.loads(m) for m in raw_metrics]
        successful = [m for m in metrics if m["success"]]

        if not successful:
            return {
                "total_requests": len(metrics),
                "success_rate": 0,
                "message": "No successful requests yet",
            }

        return {
            "total_requests": len(metrics),
            "success_rate": (len(successful) / len(metrics)) * 100,
            "avg_duration_ms": sum(m["duration_ms"] for m in successful)
            / len(successful),
            "avg_mappings_found": sum(m["mappings_found"] for m in successful)
            / len(successful),
            "avg_confidence": sum(m["confidence"] for m in successful)
            / len(successful),
            "avg_blocking_quality": sum(m["blocking_quality"] for m in successful)
            / len(successful),
            "ml_models_used_pct": (
                sum(1 for m in successful if m["ml_models_used"]) / len(successful)
            )
            * 100,
            "recent_failures": [m for m in metrics[:10] if not m["success"]],
        }

    def track_decorator(self):
        """Decorator to automatically track function metrics"""

        def decorator(func):
            @wraps(func)
            async def wrapper(*args, **kwargs):
                start_time = time.time()
                job_id = kwargs.get("job_id", "unknown")

                try:
                    result = await func(*args, **kwargs)
                    duration_ms = (time.time() - start_time) * 1000
                    self.track_configuration_request(
                        job_id, duration_ms, result, success=True
                    )
                    return result

                except Exception as e:
                    duration_ms = (time.time() - start_time) * 1000
                    self.track_configuration_request(
                        job_id, duration_ms, {"error": str(e)}, success=False
                    )
                    raise

            return wrapper

        return decorator


# Global instance
metrics_tracker = IntelligenceMetricsTracker()
