"""
Extended tests for news core storage module.
Tests BaseStorage interface methods and abstract class behavior.
"""

import pytest


class TestBaseStorageInterface:
    """Tests for BaseStorage abstract interface."""

    def test_base_storage_is_abstract(self):
        """Test BaseStorage is an abstract class."""
        from local_deep_research.news.core.storage import BaseStorage

        # Should not be able to instantiate directly
        with pytest.raises(TypeError):
            BaseStorage()

    def test_base_storage_has_create_method(self):
        """Test BaseStorage declares create method."""
        from local_deep_research.news.core.storage import BaseStorage

        assert hasattr(BaseStorage, "create")

    def test_base_storage_has_get_method(self):
        """Test BaseStorage declares get method."""
        from local_deep_research.news.core.storage import BaseStorage

        assert hasattr(BaseStorage, "get")

    def test_base_storage_has_update_method(self):
        """Test BaseStorage declares update method."""
        from local_deep_research.news.core.storage import BaseStorage

        assert hasattr(BaseStorage, "update")

    def test_base_storage_has_delete_method(self):
        """Test BaseStorage declares delete method."""
        from local_deep_research.news.core.storage import BaseStorage

        assert hasattr(BaseStorage, "delete")

    def test_base_storage_has_list_method(self):
        """Test BaseStorage declares list method."""
        from local_deep_research.news.core.storage import BaseStorage

        assert hasattr(BaseStorage, "list")


class TestConcreteStorageImplementation:
    """Tests for concrete storage implementations."""

    def test_can_create_concrete_subclass(self):
        """Test can create a concrete subclass of BaseStorage."""
        from local_deep_research.news.core.storage import BaseStorage

        class ConcreteStorage(BaseStorage):
            def create(self, data):
                return "created"

            def get(self, item_id):
                return {"id": item_id}

            def update(self, item_id, data):
                return True

            def delete(self, item_id):
                return True

            def list(self, filters=None, limit=100, offset=0):
                return []

        storage = ConcreteStorage()
        assert storage is not None

    def test_concrete_subclass_create(self):
        """Test concrete subclass create method."""
        from local_deep_research.news.core.storage import BaseStorage

        class ConcreteStorage(BaseStorage):
            def create(self, data):
                return f"id-{data.get('name', 'unknown')}"

            def get(self, item_id):
                return None

            def update(self, item_id, data):
                return False

            def delete(self, item_id):
                return False

            def list(self, filters=None, limit=100, offset=0):
                return []

        storage = ConcreteStorage()
        result = storage.create({"name": "test"})
        assert result == "id-test"

    def test_concrete_subclass_get(self):
        """Test concrete subclass get method."""
        from local_deep_research.news.core.storage import BaseStorage

        class ConcreteStorage(BaseStorage):
            def __init__(self):
                self._data = {"item-1": {"id": "item-1", "name": "Test"}}

            def create(self, data):
                return ""

            def get(self, item_id):
                return self._data.get(item_id)

            def update(self, item_id, data):
                return False

            def delete(self, item_id):
                return False

            def list(self, filters=None, limit=100, offset=0):
                return list(self._data.values())

        storage = ConcreteStorage()
        result = storage.get("item-1")
        assert result["name"] == "Test"


class TestStorageInterfaceEdgeCases:
    """Edge case tests for storage interface."""

    def test_incomplete_implementation_raises_error(self):
        """Test incomplete implementation raises TypeError."""
        from local_deep_research.news.core.storage import BaseStorage

        # Missing some abstract methods
        class IncompleteStorage(BaseStorage):
            def create(self, data):
                return "created"

            def get(self, item_id):
                return None

            # Missing update, delete, list

        with pytest.raises(TypeError):
            IncompleteStorage()

    def test_list_with_filters(self):
        """Test list method accepts filters."""
        from local_deep_research.news.core.storage import BaseStorage

        class FilterStorage(BaseStorage):
            def __init__(self):
                self._items = [
                    {"id": "1", "type": "A"},
                    {"id": "2", "type": "B"},
                    {"id": "3", "type": "A"},
                ]

            def create(self, data):
                return ""

            def get(self, item_id):
                return None

            def update(self, item_id, data):
                return False

            def delete(self, item_id):
                return False

            def list(self, filters=None, limit=100, offset=0):
                items = self._items
                if filters and "type" in filters:
                    items = [i for i in items if i["type"] == filters["type"]]
                return items[offset : offset + limit]

        storage = FilterStorage()
        result = storage.list(filters={"type": "A"})
        assert len(result) == 2

    def test_list_with_pagination(self):
        """Test list method supports pagination."""
        from local_deep_research.news.core.storage import BaseStorage

        class PaginatedStorage(BaseStorage):
            def __init__(self):
                self._items = [{"id": str(i)} for i in range(100)]

            def create(self, data):
                return ""

            def get(self, item_id):
                return None

            def update(self, item_id, data):
                return False

            def delete(self, item_id):
                return False

            def list(self, filters=None, limit=100, offset=0):
                return self._items[offset : offset + limit]

        storage = PaginatedStorage()
        result = storage.list(limit=10, offset=20)
        assert len(result) == 10
        assert result[0]["id"] == "20"


class TestCardStorageInterface:
    """Tests for CardStorage interface."""

    def test_card_storage_is_abstract(self):
        """Test CardStorage is abstract."""
        from local_deep_research.news.core.storage import CardStorage

        with pytest.raises(TypeError):
            CardStorage()

    def test_card_storage_has_get_by_user(self):
        """Test CardStorage declares get_by_user method."""
        from local_deep_research.news.core.storage import CardStorage

        assert hasattr(CardStorage, "get_by_user")

    def test_card_storage_has_add_version(self):
        """Test CardStorage declares add_version method."""
        from local_deep_research.news.core.storage import CardStorage

        assert hasattr(CardStorage, "add_version")


class TestRatingStorageInterface:
    """Tests for RatingStorage interface."""

    def test_rating_storage_is_abstract(self):
        """Test RatingStorage is abstract."""
        from local_deep_research.news.core.storage import RatingStorage

        with pytest.raises(TypeError):
            RatingStorage()

    def test_rating_storage_has_upsert_rating(self):
        """Test RatingStorage declares upsert_rating method."""
        from local_deep_research.news.core.storage import RatingStorage

        assert hasattr(RatingStorage, "upsert_rating")

    def test_rating_storage_has_get_user_ratings(self):
        """Test RatingStorage declares get_user_ratings method."""
        from local_deep_research.news.core.storage import RatingStorage

        assert hasattr(RatingStorage, "get_user_ratings")


class TestPreferenceStorageInterface:
    """Tests for PreferenceStorage interface."""

    def test_preference_storage_is_abstract(self):
        """Test PreferenceStorage is abstract."""
        from local_deep_research.news.core.storage import PreferenceStorage

        with pytest.raises(TypeError):
            PreferenceStorage()

    def test_preference_storage_has_upsert_preferences(self):
        """Test PreferenceStorage declares upsert_preferences."""
        from local_deep_research.news.core.storage import PreferenceStorage

        assert hasattr(PreferenceStorage, "upsert_preferences")

    def test_preference_storage_has_get_user_preferences(self):
        """Test PreferenceStorage declares get_user_preferences."""
        from local_deep_research.news.core.storage import PreferenceStorage

        assert hasattr(PreferenceStorage, "get_user_preferences")


class TestStorageInheritance:
    """Tests for storage interface inheritance."""

    def test_card_storage_inherits_base(self):
        """Test CardStorage inherits from BaseStorage."""
        from local_deep_research.news.core.storage import (
            CardStorage,
            BaseStorage,
        )

        assert issubclass(CardStorage, BaseStorage)

    def test_rating_storage_inherits_base(self):
        """Test RatingStorage inherits from BaseStorage."""
        from local_deep_research.news.core.storage import (
            RatingStorage,
            BaseStorage,
        )

        assert issubclass(RatingStorage, BaseStorage)

    def test_preference_storage_inherits_base(self):
        """Test PreferenceStorage inherits from BaseStorage."""
        from local_deep_research.news.core.storage import (
            PreferenceStorage,
            BaseStorage,
        )

        assert issubclass(PreferenceStorage, BaseStorage)


class TestGenerateIdFunction:
    """Tests for generate_id utility function if present."""

    def test_generate_id_returns_string(self):
        """Test generate_id returns a string."""
        try:
            from local_deep_research.news.core.storage import generate_id

            result = generate_id()
            assert isinstance(result, str)
        except ImportError:
            # Function may not exist, skip
            pytest.skip("generate_id not available")

    def test_generate_id_returns_unique(self):
        """Test generate_id returns unique values."""
        try:
            from local_deep_research.news.core.storage import generate_id

            ids = [generate_id() for _ in range(100)]
            assert len(set(ids)) == 100
        except ImportError:
            pytest.skip("generate_id not available")
