"""Tests for analytics dashboard and exporters."""

from __future__ import annotations

import json
import tempfile
from pathlib import Path

import pytest

from cleave.analytics import (
    generate_analytics,
    get_slow_operations,
    get_trends,
)
from cleave.analytics.exporters import (
    export_json,
    export_markdown,
    export_prometheus,
    export_yaml,
)
from cleave.core.performance import clear_metrics, record_metric


@pytest.fixture
def sample_metrics():
    """Create sample metrics for testing."""
    clear_metrics()

    # Record some sample metrics
    for i in range(5):
        record_metric("operation_a", {
            "count": i + 1,
            "total_time": (i + 1) * 0.5,
            "avg_time": 0.5,
        })

    record_metric("operation_b", {
        "count": 3,
        "total_time": 1.5,
        "avg_time": 0.5,
    })

    record_metric("slow_operation", {
        "count": 2,
        "total_time": 10.0,
        "avg_time": 5.0,
        "max_time": 6.0,
    })

    record_metric("memory_heavy", {
        "count": 1,
        "peak_memory_mb": 500.0,
        "avg_memory_mb": 450.0,
    })

    yield

    clear_metrics()


def test_generate_analytics(sample_metrics):
    """Test analytics generation."""
    analytics = generate_analytics()

    assert "total_operations" in analytics
    assert "total_executions" in analytics
    assert analytics["total_operations"] >= 4
    assert "operations" in analytics


def test_get_slow_operations(sample_metrics):
    """Test identification of slow operations."""
    slow_ops = get_slow_operations(threshold_seconds=1.0)

    assert len(slow_ops) > 0
    assert any(op["name"] == "slow_operation" for op in slow_ops)

    # Verify slowest operation is first
    if len(slow_ops) > 1:
        assert slow_ops[0]["avg_time"] >= slow_ops[1]["avg_time"]


def test_get_trends(sample_metrics):
    """Test trend analysis."""
    trends = get_trends()

    assert "operations" in trends
    # Should have trend data for operations with multiple executions


def test_export_json(sample_metrics):
    """Test JSON export."""
    analytics = generate_analytics()
    output = export_json(analytics)

    # Should be valid JSON
    data = json.loads(output)
    assert "total_operations" in data
    assert "operations" in data


def test_export_yaml(sample_metrics):
    """Test YAML export."""
    analytics = generate_analytics()
    output = export_yaml(analytics)

    # Should contain YAML content
    assert "total_operations:" in output
    assert "operations:" in output


def test_export_markdown(sample_metrics):
    """Test Markdown export."""
    analytics = generate_analytics()
    output = export_markdown(analytics)

    # Should have markdown headers
    assert "# Performance Analytics" in output
    assert "##" in output
    # Should have table formatting
    assert "|" in output


def test_export_prometheus(sample_metrics):
    """Test Prometheus export."""
    analytics = generate_analytics()
    output = export_prometheus(analytics)

    # Should have Prometheus metric format
    assert "cleave_operation_count" in output or "# HELP" in output
    # Should have metric values


def test_slow_operations_threshold():
    """Test slow operations with different thresholds."""
    clear_metrics()

    record_metric("fast_op", {"count": 1, "avg_time": 0.1})
    record_metric("medium_op", {"count": 1, "avg_time": 0.5})
    record_metric("slow_op", {"count": 1, "avg_time": 2.0})

    # Low threshold - all operations
    slow = get_slow_operations(threshold_seconds=0.0)
    assert len(slow) == 3

    # Medium threshold - only medium and slow
    slow = get_slow_operations(threshold_seconds=0.3)
    assert len(slow) == 2

    # High threshold - only slow
    slow = get_slow_operations(threshold_seconds=1.0)
    assert len(slow) == 1
    assert slow[0]["name"] == "slow_op"

    clear_metrics()


def test_memory_hotspots(sample_metrics):
    """Test identification of memory hotspots."""
    from cleave.analytics import get_memory_hotspots

    hotspots = get_memory_hotspots(threshold_mb=100.0)

    assert len(hotspots) > 0
    assert any(op["name"] == "memory_heavy" for op in hotspots)


def test_analytics_summary_stats(sample_metrics):
    """Test summary statistics in analytics."""
    analytics = generate_analytics()

    # Should have summary stats
    assert "summary" in analytics
    summary = analytics["summary"]

    assert "total_time" in summary
    assert "avg_time" in summary
    assert summary["total_time"] > 0


def test_export_to_file(sample_metrics):
    """Test exporting analytics to files."""
    analytics = generate_analytics()

    with tempfile.TemporaryDirectory() as tmpdir:
        tmppath = Path(tmpdir)

        # Export JSON
        json_file = tmppath / "analytics.json"
        json_file.write_text(export_json(analytics))
        assert json_file.exists()
        assert json.loads(json_file.read_text())

        # Export YAML
        yaml_file = tmppath / "analytics.yaml"
        yaml_file.write_text(export_yaml(analytics))
        assert yaml_file.exists()

        # Export Markdown
        md_file = tmppath / "analytics.md"
        md_file.write_text(export_markdown(analytics))
        assert md_file.exists()

        # Export Prometheus
        prom_file = tmppath / "analytics.prom"
        prom_file.write_text(export_prometheus(analytics))
        assert prom_file.exists()


def test_empty_metrics_analytics():
    """Test analytics generation with no metrics."""
    clear_metrics()

    analytics = generate_analytics()

    assert analytics["total_operations"] == 0
    assert analytics["total_executions"] == 0
    assert len(analytics["operations"]) == 0


def test_performance_regression_detection():
    """Test detection of performance regressions."""
    from cleave.analytics import detect_regressions

    clear_metrics()

    # Simulate a regression - operation getting slower
    record_metric("regressing_op", {
        "count": 10,
        "total_time": 5.0,
        "avg_time": 0.5,
        "last_time": 1.5,  # Last execution much slower
    })

    regressions = detect_regressions()

    # Should detect the regression (last_time > 2x avg_time)
    assert len(regressions) > 0
    assert any(r["operation"] == "regressing_op" for r in regressions)

    clear_metrics()
