"""Tests for HeuristicEpitopeScorer."""
import pytest

from peptidegym.peptide.epitope_scoring import HeuristicEpitopeScorer


@pytest.fixture
def scorer():
    return HeuristicEpitopeScorer()


def test_scorer_returns_dict(scorer):
    """score() returns a dictionary."""
    result = scorer.score("ALAAAAAAV")
    assert isinstance(result, dict)


def test_binding_score_good_anchors(scorer):
    """L at P2 and V at C-terminal are ideal HLA-A*02:01 anchors."""
    result = scorer.score("ALAAAAAAV")
    # P2=L (0.9), C-term=V (0.9), avg = 0.9
    assert result["binding_score"] > 0.7


def test_binding_score_bad_anchors(scorer):
    """G at P2 and G at C-terminal are poor anchors."""
    result = scorer.score("AGAAAAAAAG")
    assert result["binding_score"] < 0.3


def test_binding_score_range(scorer):
    """binding_score should be in [0, 1]."""
    for seq in ["ALAAAAAAV", "GGGGGGGG", "WWWWWWWWW"]:
        result = scorer.score(seq)
        assert 0.0 <= result["binding_score"] <= 1.0


def test_self_dissimilarity_range(scorer):
    """self_dissimilarity should be in [0, 1]."""
    result = scorer.score("ALAAAAAAV")
    assert 0.0 <= result["self_dissimilarity"] <= 1.0


def test_immunogenicity_hydrophobic_core(scorer):
    """Hydrophobic TCR-facing residues (positions 3-6) should boost immunogenicity."""
    # Position 3-6 (0-indexed) are LLLL — very hydrophobic
    hydrophobic_core = scorer.score("AAALLLLAAV")
    # Position 3-6 are GGGG — not hydrophobic
    neutral_core = scorer.score("AAAGGGGGAV")
    assert hydrophobic_core["immunogenicity_proxy"] > neutral_core["immunogenicity_proxy"]


def test_immunogenicity_hydrophilic_core(scorer):
    """Hydrophilic TCR-facing residues should give lower immunogenicity."""
    result = scorer.score("AAADDDDDAV")
    # D is very hydrophilic, Kyte-Doolittle = -3.5
    # immunogenicity = (-3.5 + 4.5) / 9.0 = ~0.11
    assert result["immunogenicity_proxy"] < 0.5


def test_length_fitness_9mer(scorer):
    """9-mer epitope should have length_fitness = 1.0."""
    result = scorer.score("AAAAAAAAA")  # 9-mer
    assert result["length_fitness"] == pytest.approx(1.0)


def test_length_fitness_8mer(scorer):
    """8-mer should have length_fitness = 0.8."""
    result = scorer.score("AAAAAAAA")  # 8-mer
    assert result["length_fitness"] == pytest.approx(0.8)


def test_length_fitness_10mer(scorer):
    """10-mer should have length_fitness = 0.8."""
    result = scorer.score("AAAAAAAAAA")  # 10-mer
    assert result["length_fitness"] == pytest.approx(0.8)


def test_length_fitness_7mer(scorer):
    """7-mer is outside MHC-I range, length_fitness should be 0.0."""
    result = scorer.score("AAAAAAA")  # 7-mer
    assert result["length_fitness"] == pytest.approx(0.0)


def test_scorer_minimum_length(scorer):
    """Very short sequence (1 residue) should not crash."""
    result = scorer.score("A")
    assert isinstance(result, dict)
    assert len(result) == 4
