"""High-value tests for news/rating_system/base_rater.py.

Covers enums, ABC enforcement, QualityRatingSystem and RelevanceRatingSystem
validation, rating records, and default method behavior.
"""

import pytest

from local_deep_research.news.rating_system.base_rater import (
    BaseRatingSystem,
    QualityRating,
    QualityRatingSystem,
    RelevanceRating,
    RelevanceRatingSystem,
)


class TestRatingEnums:
    """Test rating enum values."""

    def test_relevance_up_value(self):
        assert RelevanceRating.UP.value == "up"

    def test_relevance_down_value(self):
        assert RelevanceRating.DOWN.value == "down"

    def test_quality_star_values(self):
        assert QualityRating.ONE_STAR.value == 1
        assert QualityRating.FIVE_STARS.value == 5

    def test_quality_has_five_levels(self):
        assert len(QualityRating) == 5


class TestBaseRatingSystemABC:
    """Test BaseRatingSystem abstract base class."""

    def test_cannot_instantiate_directly(self):
        with pytest.raises(TypeError):
            BaseRatingSystem()

    def test_incomplete_subclass_raises(self):
        class Incomplete(BaseRatingSystem):
            pass

        with pytest.raises(TypeError):
            Incomplete()

    def test_rating_type_set_from_class_name(self):
        """rating_type is set to the class name."""
        system = QualityRatingSystem()
        assert system.rating_type == "QualityRatingSystem"


class TestBaseRatingSystemDefaults:
    """Test default method implementations."""

    def test_get_recent_ratings_returns_empty(self):
        """Default get_recent_ratings returns empty list."""
        system = QualityRatingSystem()
        assert system.get_recent_ratings("user1") == []

    def test_get_card_ratings_returns_zero(self):
        """Default get_card_ratings returns zero total."""
        system = QualityRatingSystem()
        result = system.get_card_ratings("card1")
        assert result["total"] == 0
        assert result["average"] is None

    def test_remove_rating_returns_false(self):
        """Default remove_rating returns False."""
        system = QualityRatingSystem()
        assert system.remove_rating("user1", "card1") is False


class TestBaseRatingSystemValidation:
    """Test _validate_rating_value."""

    def test_none_value_raises(self):
        """None rating value raises ValueError."""
        system = QualityRatingSystem()
        with pytest.raises(ValueError, match="cannot be None"):
            system._validate_rating_value(None)


class TestCreateRatingRecord:
    """Test _create_rating_record helper."""

    def test_record_has_expected_keys(self):
        system = QualityRatingSystem()
        record = system._create_rating_record(
            "user1", "card1", QualityRating.FIVE_STARS
        )
        expected_keys = {
            "user_id",
            "card_id",
            "rating_type",
            "rating_value",
            "rated_at",
            "metadata",
        }
        assert set(record.keys()) == expected_keys

    def test_record_metadata_defaults_to_empty_dict(self):
        system = QualityRatingSystem()
        record = system._create_rating_record("u", "c", QualityRating.ONE_STAR)
        assert record["metadata"] == {}

    def test_record_preserves_metadata(self):
        system = QualityRatingSystem()
        meta = {"source": "test"}
        record = system._create_rating_record(
            "u", "c", QualityRating.ONE_STAR, metadata=meta
        )
        assert record["metadata"]["source"] == "test"

    def test_record_rating_type_from_get_rating_type(self):
        system = QualityRatingSystem()
        record = system._create_rating_record("u", "c", QualityRating.ONE_STAR)
        assert record["rating_type"] == "quality"


class TestQualityRatingSystem:
    """Test QualityRatingSystem."""

    def test_get_rating_type(self):
        assert QualityRatingSystem().get_rating_type() == "quality"

    def test_rate_success(self):
        system = QualityRatingSystem()
        result = system.rate("user1", "card1", QualityRating.FOUR_STARS)
        assert result["success"] is True
        assert "4 stars" in result["message"]

    def test_rate_invalid_value_raises(self):
        """Non-QualityRating value raises ValueError."""
        system = QualityRatingSystem()
        with pytest.raises(ValueError, match="QualityRating"):
            system.rate("user1", "card1", "invalid")

    def test_rate_integer_raises(self):
        """Plain integer raises ValueError (must be enum)."""
        system = QualityRatingSystem()
        with pytest.raises(ValueError):
            system.rate("user1", "card1", 5)

    def test_get_rating_no_backend_returns_none(self):
        system = QualityRatingSystem()
        assert system.get_rating("user1", "card1") is None


class TestRelevanceRatingSystem:
    """Test RelevanceRatingSystem."""

    def test_get_rating_type(self):
        assert RelevanceRatingSystem().get_rating_type() == "relevance"

    def test_rate_up(self):
        system = RelevanceRatingSystem()
        result = system.rate("user1", "card1", RelevanceRating.UP)
        assert result["success"] is True
        assert "thumbs up" in result["message"]

    def test_rate_down(self):
        system = RelevanceRatingSystem()
        result = system.rate("user1", "card1", RelevanceRating.DOWN)
        assert result["success"] is True
        assert "thumbs down" in result["message"]

    def test_rate_invalid_value_raises(self):
        system = RelevanceRatingSystem()
        with pytest.raises(ValueError, match="RelevanceRating"):
            system.rate("user1", "card1", "thumbs_up")

    def test_get_rating_no_backend_returns_none(self):
        system = RelevanceRatingSystem()
        assert system.get_rating("user1", "card1") is None
