"""Tests for analysis/svd_labels module."""


def test_canonical_party_sets_contain_expected_parties():
    """Verify CANONICAL_RIGHT and CANONICAL_LEFT contain the expected parties."""
    from analysis.config import CANONICAL_LEFT, CANONICAL_RIGHT

    assert "PVV" in CANONICAL_RIGHT
    assert "FVD" in CANONICAL_RIGHT
    assert "JA21" in CANONICAL_RIGHT
    assert "SGP" in CANONICAL_RIGHT

    assert "SP" in CANONICAL_LEFT
    assert "PvdA" in CANONICAL_LEFT
    assert "PvdD" in CANONICAL_LEFT
    assert "DENK" in CANONICAL_LEFT
    assert "Volt" in CANONICAL_LEFT


def test_compute_flip_direction_uses_all_canonical_right_parties():
    """Test that flip computation correctly uses all four canonical right parties."""
    from analysis.config import CANONICAL_LEFT, CANONICAL_RIGHT
    from analysis.svd_labels import compute_flip_direction

    # Build party scores where ALL canonical right parties are on the left (negative)
    # and ALL canonical left parties are on the right (positive)
    party_scores = {}
    for party in CANONICAL_RIGHT:
        party_scores[party] = [-0.5]
    for party in CANONICAL_LEFT:
        party_scores[party] = [0.5]

    # All right parties on left → should flip
    assert compute_flip_direction(1, party_scores) is True

    # Invert: all right parties on right (positive), left parties on left (negative)
    party_scores_inverted = {}
    for party in CANONICAL_RIGHT:
        party_scores_inverted[party] = [0.5]
    for party in CANONICAL_LEFT:
        party_scores_inverted[party] = [-0.5]

    # All right parties on right → should not flip
    assert compute_flip_direction(1, party_scores_inverted) is False


def test_compute_flip_direction_all_components_canonical_parties():
    """Test flip for all 10 components using full canonical party sets."""
    from analysis.config import CANONICAL_LEFT, CANONICAL_RIGHT
    from analysis.svd_labels import compute_flip_direction

    # Right parties on left (negative), left parties on right (positive)
    party_scores = {}
    for party in CANONICAL_RIGHT:
        party_scores[party] = [-0.7] * 10
    for party in CANONICAL_LEFT:
        party_scores[party] = [0.3] * 10

    for comp in range(1, 11):
        flip = compute_flip_direction(comp, party_scores)
        assert flip is True, f"Component {comp} should flip (right parties on left)"

    # Inverted: right on right, left on left
    party_scores_inverted = {}
    for party in CANONICAL_RIGHT:
        party_scores_inverted[party] = [0.7] * 10
    for party in CANONICAL_LEFT:
        party_scores_inverted[party] = [-0.3] * 10

    for comp in range(1, 11):
        flip = compute_flip_direction(comp, party_scores_inverted)
        assert flip is False, (
            f"Component {comp} should not flip (right parties on right)"
        )


def test_get_svd_label_returns_correct_label():
    """Test that get_svd_label returns the correct label for each component."""
    from analysis.svd_labels import get_svd_label

    # Component 1 should return "Economische sectorbelangen versus sociale welvaart"
    label1 = get_svd_label(1)
    assert "Economische sectorbelangen" in label1 or "sectorbelangen" in label1.lower()

    # Component 2 should return "Nationalistische versus multilateralistische oriëntatie"
    label2 = get_svd_label(2)
    assert "Nationalistisch" in label2 or "nationalistisch" in label2.lower()

    # Component 3 should return "Verzorgingsstaat versus defensie en nationale veiligheid"
    label3 = get_svd_label(3)
    assert "Verzorgingsstaat" in label3 or "verzorgingsstaat" in label3.lower()


def test_compute_flip_direction_right_on_left():
    """Test that flip is True when right parties are on the left."""
    from analysis.svd_labels import compute_flip_direction

    # Right parties (PVV, FVD) have negative scores (on left), left parties have positive
    party_scores = {
        "PVV": [-0.8, 0.0],  # Right party
        "FVD": [-0.6, 0.0],  # Right party
        "SP": [0.6, 0.0],  # Left party
        "DENK": [0.4, 0.0],  # Left party
    }

    # Component 1: right_mean = -0.7, left_mean = 0.5
    # right_mean < left_mean, so flip = True
    assert compute_flip_direction(1, party_scores) is True


def test_compute_flip_direction_right_on_right():
    """Test that flip is False when right parties are already on the right."""
    from analysis.svd_labels import compute_flip_direction

    # Right parties (PVV, FVD) have positive scores (on right), left parties have negative
    party_scores = {
        "PVV": [0.8, 0.0],  # Right party
        "FVD": [0.6, 0.0],  # Right party
        "SP": [-0.6, 0.0],  # Left party
        "DENK": [-0.4, 0.0],  # Left party
    }

    # Component 1: right_mean = 0.7, left_mean = -0.5
    # right_mean > left_mean, so flip = False
    assert compute_flip_direction(1, party_scores) is False


def test_compute_flip_direction_insufficient_data():
    """Test that flip is False when there's insufficient data."""
    from analysis.svd_labels import compute_flip_direction

    # No right parties in data
    party_scores = {
        "SP": [0.6, 0.0],
        "DENK": [0.4, 0.0],
    }

    assert compute_flip_direction(1, party_scores) is False

    # No left parties in data
    party_scores = {
        "VVD": [0.5, 0.0],
        "PVV": [0.8, 0.0],
    }

    assert compute_flip_direction(1, party_scores) is False


def test_auto_flip_computation_for_all_components():
    """Test that flip directions are computed correctly for all components."""
    from analysis.svd_labels import compute_flip_direction

    # Simulate party scores for 10 components using CANONICAL_RIGHT/LEFT
    # Right parties should have positive scores on component 1
    # Left parties should have negative scores on component 1
    party_scores = {
        "PVV": [0.8] * 10,  # Right party (CANONICAL_RIGHT), positive on all
        "FVD": [0.6] * 10,  # Right party (CANONICAL_RIGHT), positive on all
        "SP": [-0.6] * 10,  # Left party (CANONICAL_LEFT), negative on all
        "DENK": [-0.4] * 10,  # Left party (CANONICAL_LEFT), negative on all
    }

    # For all components, right_mean > left_mean, so flip should be False
    for comp in range(1, 11):
        flip = compute_flip_direction(comp, party_scores)
        assert flip is False, f"Component {comp} should not flip"

    # Now test with right parties on left (negative scores)
    party_scores_left = {
        "PVV": [-0.8] * 10,  # Right party (CANONICAL_RIGHT), negative
        "FVD": [-0.6] * 10,  # Right party (CANONICAL_RIGHT), negative
        "SP": [0.6] * 10,  # Left party (CANONICAL_LEFT), positive
        "DENK": [0.4] * 10,  # Left party (CANONICAL_LEFT), positive
    }

    # For all components, right_mean < left_mean, so flip should be True
    for comp in range(1, 11):
        flip = compute_flip_direction(comp, party_scores_left)
        assert flip is True, f"Component {comp} should flip"
