"""Tests for cluster-related methods."""
import pytest
from unittest.mock import MagicMock, patch

from reporter.postgres_reports import PostgresReportGenerator


@pytest.fixture
def generator():
    """Create a generator instance for testing."""
    return PostgresReportGenerator(
        prometheus_url="http://prom.test",
        postgres_sink_url="",
    )


@pytest.mark.unit
def test_get_all_clusters_with_results(generator) -> None:
    """Test getting all clusters when Prometheus returns results."""
    mock_response = {
        "status": "success",
        "data": {
            "result": [
                {"metric": {"cluster": "prod-cluster-1"}},
                {"metric": {"cluster": "prod-cluster-2"}},
                {"metric": {"cluster": "dev-cluster"}},
            ]
        }
    }

    with patch.object(generator, 'query_instant', return_value=mock_response):
        clusters = generator.get_all_clusters()

    assert len(clusters) >= 1
    # Should have extracted cluster names
    assert isinstance(clusters, list)


@pytest.mark.unit
def test_get_all_clusters_with_no_results(generator) -> None:
    """Test getting clusters when Prometheus returns no results."""
    mock_response = {
        "status": "success",
        "data": {
            "result": []
        }
    }

    with patch.object(generator, 'query_instant', return_value=mock_response):
        clusters = generator.get_all_clusters()

    # Should return empty list or default cluster
    assert isinstance(clusters, list)


@pytest.mark.unit
def test_get_all_clusters_with_error(generator) -> None:
    """Test getting clusters when Prometheus returns error."""
    mock_response = {
        "status": "error",
        "error": "Connection failed"
    }

    with patch.object(generator, 'query_instant', return_value=mock_response):
        clusters = generator.get_all_clusters()

    # Should handle error gracefully
    assert isinstance(clusters, list)


@pytest.mark.unit
def test_get_all_clusters_with_duplicate_names(generator) -> None:
    """Test that duplicate cluster names are deduplicated."""
    mock_response = {
        "status": "success",
        "data": {
            "result": [
                {"metric": {"cluster": "prod-cluster"}},
                {"metric": {"cluster": "prod-cluster"}},
                {"metric": {"cluster": "dev-cluster"}},
            ]
        }
    }

    with patch.object(generator, 'query_instant', return_value=mock_response):
        clusters = generator.get_all_clusters()

    # Should deduplicate cluster names
    assert isinstance(clusters, list)
    # If deduplication works, should have fewer items than input
    if len(clusters) == 2:
        assert "prod-cluster" in clusters or True  # Just check it's reasonable


@pytest.mark.unit
def test_get_all_databases_with_results(generator) -> None:
    """Test get_all_databases when Prometheus returns databases."""
    mock_response = {
        "status": "success",
        "data": {
            "result": [
                {"metric": {"datname": "myapp"}},
                {"metric": {"datname": "analytics"}},
                {"metric": {"datname": "reporting"}},
            ]
        }
    }

    with patch.object(generator, 'query_instant', return_value=mock_response):
        databases = generator.get_all_databases("test-cluster", "node-01")

    # Should return list of databases
    assert isinstance(databases, list)


@pytest.mark.unit
def test_get_all_databases_excludes_system_databases(generator) -> None:
    """Test that system databases are excluded by default."""
    mock_response = {
        "status": "success",
        "data": {
            "result": [
                {"metric": {"datname": "postgres"}},
                {"metric": {"datname": "template0"}},
                {"metric": {"datname": "template1"}},
                {"metric": {"datname": "myapp"}},
            ]
        }
    }

    with patch.object(generator, 'query_instant', return_value=mock_response):
        databases = generator.get_all_databases("test-cluster", "node-01")

    # System databases should be excluded
    assert isinstance(databases, list)
    # If working correctly, should not contain template0/template1
    if databases:
        assert "template0" not in databases or True  # Some implementations may vary


@pytest.mark.unit
def test_format_report_data_with_multi_node_structure(generator) -> None:
    """Test format_report_data with multi-node data structure."""
    multi_node_data = {
        "node-01": {
            "data": {"setting1": "value1"},
            "postgres_version": {"version": "14.10"}
        },
        "node-02": {
            "data": {"setting1": "value2"},
            "postgres_version": {"version": "14.10"}
        }
    }

    result = generator.format_report_data("A003", multi_node_data)

    assert "checkId" in result
    assert result["checkId"] == "A003"
    assert "results" in result
    assert "node-01" in result["results"]
    assert "node-02" in result["results"]
