"""
Comprehensive tests for base_rater module.
Tests rating enums, BaseRatingSystem, QualityRatingSystem, and RelevanceRatingSystem.
"""

import pytest
from unittest.mock import Mock


class TestRelevanceRatingEnum:
    """Tests for RelevanceRating enum."""

    def test_has_up_value(self):
        """Test has UP value."""
        from local_deep_research.news.rating_system.base_rater import (
            RelevanceRating,
        )

        assert RelevanceRating.UP.value == "up"

    def test_has_down_value(self):
        """Test has DOWN value."""
        from local_deep_research.news.rating_system.base_rater import (
            RelevanceRating,
        )

        assert RelevanceRating.DOWN.value == "down"

    def test_is_enum(self):
        """Test RelevanceRating is an Enum."""
        from local_deep_research.news.rating_system.base_rater import (
            RelevanceRating,
        )
        from enum import Enum

        assert issubclass(RelevanceRating, Enum)

    def test_only_two_values(self):
        """Test only has two values."""
        from local_deep_research.news.rating_system.base_rater import (
            RelevanceRating,
        )

        assert len(list(RelevanceRating)) == 2


class TestQualityRatingEnum:
    """Tests for QualityRating enum."""

    def test_has_one_star(self):
        """Test has ONE_STAR value."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRating,
        )

        assert QualityRating.ONE_STAR.value == 1

    def test_has_two_stars(self):
        """Test has TWO_STARS value."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRating,
        )

        assert QualityRating.TWO_STARS.value == 2

    def test_has_three_stars(self):
        """Test has THREE_STARS value."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRating,
        )

        assert QualityRating.THREE_STARS.value == 3

    def test_has_four_stars(self):
        """Test has FOUR_STARS value."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRating,
        )

        assert QualityRating.FOUR_STARS.value == 4

    def test_has_five_stars(self):
        """Test has FIVE_STARS value."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRating,
        )

        assert QualityRating.FIVE_STARS.value == 5

    def test_is_enum(self):
        """Test QualityRating is an Enum."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRating,
        )
        from enum import Enum

        assert issubclass(QualityRating, Enum)

    def test_has_five_values(self):
        """Test has exactly five values."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRating,
        )

        assert len(list(QualityRating)) == 5


class TestBaseRatingSystemInit:
    """Tests for BaseRatingSystem initialization."""

    def test_stores_storage_backend(self):
        """Test stores storage_backend reference."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        mock_storage = Mock()
        system = QualityRatingSystem(storage_backend=mock_storage)

        assert system.storage_backend is mock_storage

    def test_accepts_none_storage(self):
        """Test accepts None for storage_backend."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem(storage_backend=None)

        assert system.storage_backend is None

    def test_sets_rating_type_from_class_name(self):
        """Test sets rating_type from class name."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()

        assert system.rating_type == "QualityRatingSystem"


class TestGetRecentRatings:
    """Tests for get_recent_ratings method."""

    def test_returns_empty_list_by_default(self):
        """Test returns empty list by default (no storage)."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()
        result = system.get_recent_ratings("user123")

        assert result == []

    def test_default_limit_is_50(self):
        """Test default limit parameter is 50."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()

        # Method signature check
        import inspect

        sig = inspect.signature(system.get_recent_ratings)
        limit_param = sig.parameters.get("limit")
        assert limit_param.default == 50


class TestGetCardRatings:
    """Tests for get_card_ratings method."""

    def test_returns_empty_summary_by_default(self):
        """Test returns empty summary by default."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()
        result = system.get_card_ratings("card123")

        assert result == {"total": 0, "average": None}

    def test_accepts_rating_type_filter(self):
        """Test accepts rating_type filter parameter."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()

        # Should not raise
        result = system.get_card_ratings("card123", rating_type="quality")

        assert isinstance(result, dict)


class TestRemoveRating:
    """Tests for remove_rating method."""

    def test_returns_false_by_default(self):
        """Test returns False by default (not implemented)."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()
        result = system.remove_rating("user123", "card456")

        assert result is False


class TestCreateRatingRecord:
    """Tests for _create_rating_record method."""

    def test_includes_user_id(self):
        """Test includes user_id in record."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()
        record = system._create_rating_record("user123", "card456", "value")

        assert record["user_id"] == "user123"

    def test_includes_card_id(self):
        """Test includes card_id in record."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()
        record = system._create_rating_record("user123", "card456", "value")

        assert record["card_id"] == "card456"

    def test_includes_rating_value(self):
        """Test includes rating_value in record."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
            QualityRating,
        )

        system = QualityRatingSystem()
        record = system._create_rating_record(
            "user", "card", QualityRating.FIVE_STARS
        )

        assert record["rating_value"] == QualityRating.FIVE_STARS

    def test_includes_rating_type(self):
        """Test includes rating_type from get_rating_type."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()
        record = system._create_rating_record("user", "card", "value")

        assert record["rating_type"] == "quality"

    def test_includes_rated_at_timestamp(self):
        """Test includes rated_at timestamp."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()
        record = system._create_rating_record("user", "card", "value")

        assert "rated_at" in record
        # Should be ISO format string
        assert isinstance(record["rated_at"], str)

    def test_includes_empty_metadata_by_default(self):
        """Test includes empty metadata by default."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()
        record = system._create_rating_record("user", "card", "value")

        assert record["metadata"] == {}

    def test_includes_provided_metadata(self):
        """Test includes provided metadata."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()
        metadata = {"source": "mobile", "context": "feed"}
        record = system._create_rating_record("user", "card", "value", metadata)

        assert record["metadata"] == metadata


class TestValidateRatingValue:
    """Tests for _validate_rating_value method."""

    def test_raises_for_none_value(self):
        """Test raises ValueError for None value."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()

        with pytest.raises(ValueError) as exc_info:
            system._validate_rating_value(None)

        assert "cannot be None" in str(exc_info.value)


class TestQualityRatingSystem:
    """Tests for QualityRatingSystem class."""

    def test_get_rating_type_returns_quality(self):
        """Test get_rating_type returns 'quality'."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()

        assert system.get_rating_type() == "quality"

    def test_rate_validates_value(self):
        """Test rate validates the rating value."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()

        with pytest.raises(ValueError):
            system.rate("user", "card", "invalid_value")

    def test_rate_accepts_quality_rating_enum(self):
        """Test rate accepts QualityRating enum values."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
            QualityRating,
        )

        system = QualityRatingSystem()
        result = system.rate("user", "card", QualityRating.FIVE_STARS)

        assert result["success"] is True

    def test_rate_returns_success_dict(self):
        """Test rate returns success dictionary."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
            QualityRating,
        )

        system = QualityRatingSystem()
        result = system.rate("user", "card", QualityRating.THREE_STARS)

        assert "success" in result
        assert "rating" in result
        assert "message" in result

    def test_rate_message_includes_star_count(self):
        """Test rate message includes star count."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
            QualityRating,
        )

        system = QualityRatingSystem()
        result = system.rate("user", "card", QualityRating.FOUR_STARS)

        assert "4 stars" in result["message"]

    def test_validate_rejects_non_quality_rating(self):
        """Test validation rejects non-QualityRating values."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
            RelevanceRating,
        )

        system = QualityRatingSystem()

        with pytest.raises(ValueError) as exc_info:
            system._validate_rating_value(RelevanceRating.UP)

        assert "QualityRating enum" in str(exc_info.value)

    def test_validate_rejects_integer(self):
        """Test validation rejects raw integer values."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()

        with pytest.raises(ValueError):
            system._validate_rating_value(5)

    def test_get_rating_returns_none_without_storage(self):
        """Test get_rating returns None without storage."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
        )

        system = QualityRatingSystem()
        result = system.get_rating("user", "card")

        assert result is None


class TestRelevanceRatingSystem:
    """Tests for RelevanceRatingSystem class."""

    def test_get_rating_type_returns_relevance(self):
        """Test get_rating_type returns 'relevance'."""
        from local_deep_research.news.rating_system.base_rater import (
            RelevanceRatingSystem,
        )

        system = RelevanceRatingSystem()

        assert system.get_rating_type() == "relevance"

    def test_rate_accepts_up_rating(self):
        """Test rate accepts UP rating."""
        from local_deep_research.news.rating_system.base_rater import (
            RelevanceRatingSystem,
            RelevanceRating,
        )

        system = RelevanceRatingSystem()
        result = system.rate("user", "card", RelevanceRating.UP)

        assert result["success"] is True

    def test_rate_accepts_down_rating(self):
        """Test rate accepts DOWN rating."""
        from local_deep_research.news.rating_system.base_rater import (
            RelevanceRatingSystem,
            RelevanceRating,
        )

        system = RelevanceRatingSystem()
        result = system.rate("user", "card", RelevanceRating.DOWN)

        assert result["success"] is True

    def test_rate_message_includes_thumbs_direction(self):
        """Test rate message includes thumbs up/down."""
        from local_deep_research.news.rating_system.base_rater import (
            RelevanceRatingSystem,
            RelevanceRating,
        )

        system = RelevanceRatingSystem()
        result = system.rate("user", "card", RelevanceRating.UP)

        assert "thumbs up" in result["message"]

    def test_validate_rejects_quality_rating(self):
        """Test validation rejects QualityRating values."""
        from local_deep_research.news.rating_system.base_rater import (
            RelevanceRatingSystem,
            QualityRating,
        )

        system = RelevanceRatingSystem()

        with pytest.raises(ValueError) as exc_info:
            system._validate_rating_value(QualityRating.FIVE_STARS)

        assert "RelevanceRating" in str(exc_info.value)

    def test_validate_rejects_string(self):
        """Test validation rejects string values."""
        from local_deep_research.news.rating_system.base_rater import (
            RelevanceRatingSystem,
        )

        system = RelevanceRatingSystem()

        with pytest.raises(ValueError):
            system._validate_rating_value("up")

    def test_get_rating_returns_none_without_storage(self):
        """Test get_rating returns None without storage."""
        from local_deep_research.news.rating_system.base_rater import (
            RelevanceRatingSystem,
        )

        system = RelevanceRatingSystem()
        result = system.get_rating("user", "card")

        assert result is None


class TestRatingSystemWithStorage:
    """Tests for rating systems with storage backend."""

    def test_quality_system_does_not_raise_with_storage(self):
        """Test quality system doesn't raise when storage is provided."""
        from local_deep_research.news.rating_system.base_rater import (
            QualityRatingSystem,
            QualityRating,
        )

        mock_storage = Mock()
        system = QualityRatingSystem(storage_backend=mock_storage)

        # Should not raise
        result = system.rate("user", "card", QualityRating.FIVE_STARS)

        assert result["success"] is True

    def test_relevance_system_does_not_raise_with_storage(self):
        """Test relevance system doesn't raise when storage is provided."""
        from local_deep_research.news.rating_system.base_rater import (
            RelevanceRatingSystem,
            RelevanceRating,
        )

        mock_storage = Mock()
        system = RelevanceRatingSystem(storage_backend=mock_storage)

        # Should not raise
        result = system.rate("user", "card", RelevanceRating.DOWN)

        assert result["success"] is True


class TestRatingSystemAbstract:
    """Tests for abstract base class behavior."""

    def test_base_rating_system_is_abstract(self):
        """Test BaseRatingSystem is abstract."""
        from local_deep_research.news.rating_system.base_rater import (
            BaseRatingSystem,
        )
        from abc import ABC

        assert issubclass(BaseRatingSystem, ABC)

    def test_cannot_instantiate_base_directly(self):
        """Test cannot instantiate BaseRatingSystem directly."""
        from local_deep_research.news.rating_system.base_rater import (
            BaseRatingSystem,
        )

        with pytest.raises(TypeError):
            BaseRatingSystem()
