"""
Tests for metrics routes aggregation.

Tests cover:
- Rating analytics
- Link analytics
- Rate limiting analytics
"""

from datetime import datetime, timedelta


class TestRatingAnalytics:
    """Tests for rating analytics."""

    def test_rating_analytics_time_filtering_7d(self):
        """7 day time filter works."""
        cutoff = datetime.now() - timedelta(days=7)
        ratings = [
            {"date": datetime.now() - timedelta(days=1), "rating": 5},
            {"date": datetime.now() - timedelta(days=10), "rating": 3},
        ]

        filtered = [r for r in ratings if r["date"] > cutoff]

        assert len(filtered) == 1

    def test_rating_analytics_time_filtering_30d(self):
        """30 day time filter works."""
        cutoff = datetime.now() - timedelta(days=30)
        ratings = [
            {"date": datetime.now() - timedelta(days=15), "rating": 4},
            {"date": datetime.now() - timedelta(days=45), "rating": 2},
        ]

        filtered = [r for r in ratings if r["date"] > cutoff]

        assert len(filtered) == 1

    def test_rating_analytics_time_filtering_all(self):
        """'All' time filter includes everything."""
        ratings = [
            {"date": datetime.now() - timedelta(days=365), "rating": 3},
            {"date": datetime.now() - timedelta(days=1), "rating": 5},
        ]

        filtered = ratings  # No cutoff

        assert len(filtered) == 2

    def test_rating_analytics_avg_calculation(self):
        """Average rating is calculated correctly."""
        ratings = [5, 4, 3, 4, 5]

        avg = sum(ratings) / len(ratings)

        assert avg == 4.2

    def test_rating_analytics_distribution_1_to_5(self):
        """Rating distribution from 1 to 5."""
        ratings = [1, 2, 3, 3, 4, 4, 4, 5, 5, 5]

        distribution = {i: ratings.count(i) for i in range(1, 6)}

        assert distribution[1] == 1
        assert distribution[3] == 2
        assert distribution[4] == 3
        assert distribution[5] == 3

    def test_rating_analytics_satisfaction_stats(self):
        """Satisfaction categories are calculated."""
        ratings = [1, 2, 3, 4, 5, 4, 5, 5, 4, 3]

        satisfied = sum(1 for r in ratings if r >= 4)
        neutral = sum(1 for r in ratings if r == 3)
        dissatisfied = sum(1 for r in ratings if r <= 2)

        assert satisfied == 6
        assert neutral == 2
        assert dissatisfied == 2

    def test_rating_analytics_empty_data_handling(self):
        """Empty ratings return default values."""
        ratings = []

        if not ratings:
            avg = 0
            {i: 0 for i in range(1, 6)}
        else:
            avg = sum(ratings) / len(ratings)

        assert avg == 0

    def test_rating_analytics_null_username_handling(self):
        """Null username entries are filtered."""
        ratings = [
            {"username": "user1", "rating": 5},
            {"username": None, "rating": 3},
            {"username": "user2", "rating": 4},
        ]

        filtered = [r for r in ratings if r["username"]]

        assert len(filtered) == 2


class TestLinkAnalytics:
    """Tests for link analytics."""

    def test_link_analytics_domain_extraction(self):
        """Domain is extracted from URL."""
        url = "https://www.example.com/path/to/page"

        from urllib.parse import urlparse

        domain = urlparse(url).netloc

        assert domain == "www.example.com"

    def test_link_analytics_www_prefix_removal(self):
        """www prefix is removed from domain."""
        domain = "www.example.com"

        clean_domain = domain.replace("www.", "")

        assert clean_domain == "example.com"

    def test_link_analytics_temporal_tracking_daily(self):
        """Daily link counts are tracked."""
        links = [
            {"date": "2024-01-01", "domain": "example.com"},
            {"date": "2024-01-01", "domain": "test.com"},
            {"date": "2024-01-02", "domain": "example.com"},
        ]

        daily_counts = {}
        for link in links:
            date = link["date"]
            daily_counts[date] = daily_counts.get(date, 0) + 1

        assert daily_counts["2024-01-01"] == 2
        assert daily_counts["2024-01-02"] == 1

    def test_link_analytics_domain_connections(self):
        """Domain connections are tracked."""
        resources = [
            {"domain": "example.com", "research_id": 1},
            {"domain": "example.com", "research_id": 2},
            {"domain": "test.com", "research_id": 1},
        ]

        domain_research_counts = {}
        for r in resources:
            domain = r["domain"]
            domain_research_counts[domain] = (
                domain_research_counts.get(domain, 0) + 1
            )

        assert domain_research_counts["example.com"] == 2

    def test_link_analytics_quality_metrics_with_title(self):
        """Links with title have higher quality."""
        resources = [
            {"url": "url1", "title": "Good Title"},
            {"url": "url2", "title": None},
        ]

        with_title = sum(1 for r in resources if r["title"])

        assert with_title == 1

    def test_link_analytics_quality_metrics_with_preview(self):
        """Links with preview have higher quality."""
        resources = [
            {"url": "url1", "preview": "Some preview text"},
            {"url": "url2", "preview": ""},
        ]

        with_preview = sum(1 for r in resources if r["preview"])

        assert with_preview == 1

    def test_link_analytics_top_10_domains(self):
        """Top 10 domains are returned."""
        domain_counts = {f"domain{i}.com": 100 - i for i in range(20)}

        top_10 = dict(
            sorted(domain_counts.items(), key=lambda x: x[1], reverse=True)[:10]
        )

        assert len(top_10) == 10
        assert "domain0.com" in top_10

    def test_link_analytics_domain_distribution(self):
        """Domain distribution percentages are calculated."""
        domain_counts = {"a.com": 50, "b.com": 30, "c.com": 20}
        total = sum(domain_counts.values())

        distribution = {k: v / total * 100 for k, v in domain_counts.items()}

        assert distribution["a.com"] == 50.0
        assert distribution["b.com"] == 30.0

    def test_link_analytics_source_type_analysis(self):
        """Source types are analyzed."""
        resources = [
            {"type": "webpage"},
            {"type": "pdf"},
            {"type": "webpage"},
            {"type": "video"},
        ]

        type_counts = {}
        for r in resources:
            t = r["type"]
            type_counts[t] = type_counts.get(t, 0) + 1

        assert type_counts["webpage"] == 2

    def test_link_analytics_category_distribution(self):
        """Categories are distributed correctly."""
        categories = [
            "news",
            "academic",
            "news",
            "blog",
            "academic",
            "academic",
        ]

        distribution = {}
        for cat in categories:
            distribution[cat] = distribution.get(cat, 0) + 1

        assert distribution["academic"] == 3
        assert distribution["news"] == 2

    def test_link_analytics_temporal_trend(self):
        """Temporal trends are detected."""
        daily_counts = [10, 12, 15, 18, 20, 22, 25]

        # Trend is increasing
        trend = (
            "increasing" if daily_counts[-1] > daily_counts[0] else "decreasing"
        )

        assert trend == "increasing"

    def test_link_analytics_empty_results(self):
        """Empty results return default values."""
        resources = []

        if not resources:
            result = {"domains": [], "total": 0}
        else:
            result = {"domains": [], "total": len(resources)}

        assert result["total"] == 0


class TestRateLimitingAnalytics:
    """Tests for rate limiting analytics."""

    def test_rate_limiting_analytics_unix_timestamp_cutoff(self):
        """Unix timestamp cutoff is used."""
        import time

        current_time = time.time()
        cutoff_7d = current_time - (7 * 24 * 60 * 60)

        assert cutoff_7d < current_time

    def test_rate_limiting_analytics_per_engine_stats(self):
        """Per-engine statistics are calculated."""
        attempts = [
            {"engine": "google", "success": True},
            {"engine": "google", "success": False},
            {"engine": "bing", "success": True},
        ]

        engine_stats = {}
        for a in attempts:
            engine = a["engine"]
            if engine not in engine_stats:
                engine_stats[engine] = {"success": 0, "failed": 0}
            if a["success"]:
                engine_stats[engine]["success"] += 1
            else:
                engine_stats[engine]["failed"] += 1

        assert engine_stats["google"]["success"] == 1
        assert engine_stats["google"]["failed"] == 1

    def test_rate_limiting_analytics_base_wait_calculation(self):
        """Base wait time is calculated."""
        attempts = [
            {"wait_time": 1.0},
            {"wait_time": 2.0},
            {"wait_time": 1.5},
        ]

        avg_wait = sum(a["wait_time"] for a in attempts) / len(attempts)

        assert avg_wait == 1.5

    def test_rate_limiting_analytics_success_rate_calculation(self):
        """Success rate is calculated correctly."""
        total = 100
        successful = 85

        success_rate = (successful / total) * 100

        assert success_rate == 85.0

    def test_rate_limiting_analytics_status_healthy(self):
        """Health status is 'healthy' when success rate high."""
        success_rate = 95

        if success_rate >= 90:
            status = "healthy"
        elif success_rate >= 70:
            status = "degraded"
        else:
            status = "poor"

        assert status == "healthy"

    def test_rate_limiting_analytics_status_degraded(self):
        """Health status is 'degraded' when success rate moderate."""
        success_rate = 80

        if success_rate >= 90:
            status = "healthy"
        elif success_rate >= 70:
            status = "degraded"
        else:
            status = "poor"

        assert status == "degraded"

    def test_rate_limiting_analytics_status_poor(self):
        """Health status is 'poor' when success rate low."""
        success_rate = 50

        if success_rate >= 90:
            status = "healthy"
        elif success_rate >= 70:
            status = "degraded"
        else:
            status = "poor"

        assert status == "poor"

    def test_rate_limiting_analytics_average_wait_times(self):
        """Average wait times per engine."""
        attempts = [
            {"engine": "google", "wait_time": 1.0},
            {"engine": "google", "wait_time": 2.0},
            {"engine": "bing", "wait_time": 0.5},
        ]

        engine_waits = {}
        for a in attempts:
            engine = a["engine"]
            if engine not in engine_waits:
                engine_waits[engine] = []
            engine_waits[engine].append(a["wait_time"])

        avg_waits = {e: sum(w) / len(w) for e, w in engine_waits.items()}

        assert avg_waits["google"] == 1.5
        assert avg_waits["bing"] == 0.5

    def test_rate_limiting_analytics_empty_data(self):
        """Empty data returns defaults."""
        attempts = []

        if not attempts:
            result = {"engines": {}, "total_attempts": 0}
        else:
            result = {}

        assert result["total_attempts"] == 0

    def test_rate_limiting_analytics_multiple_engines(self):
        """Multiple engines are tracked separately."""
        engines = ["google", "bing", "duckduckgo"]

        engine_data = {e: {"attempts": 0, "success": 0} for e in engines}

        assert len(engine_data) == 3
        assert "google" in engine_data
