"""
Tests for news/core/base_card.py

Tests cover:
- CardSource dataclass
- CardVersion dataclass
- BaseCard abstract class
- Card initialization and field generation
"""

import pytest
from unittest.mock import Mock
from dataclasses import is_dataclass
from abc import ABC


class TestCardSourceDataclass:
    """Tests for CardSource dataclass."""

    def test_card_source_is_dataclass(self):
        """CardSource is a dataclass."""
        from local_deep_research.news.core.base_card import CardSource

        assert is_dataclass(CardSource)

    def test_card_source_required_type_field(self):
        """CardSource requires type field."""
        from local_deep_research.news.core.base_card import CardSource

        source = CardSource(type="news_item")
        assert source.type == "news_item"

    def test_card_source_optional_fields_defaults(self):
        """CardSource has optional fields with defaults."""
        from local_deep_research.news.core.base_card import CardSource

        source = CardSource(type="test")

        assert source.source_id is None
        assert source.created_from == ""
        assert source.metadata == {}

    def test_card_source_custom_metadata(self):
        """CardSource accepts custom metadata."""
        from local_deep_research.news.core.base_card import CardSource

        source = CardSource(
            type="test",
            metadata={"query": "test query", "timestamp": "2024-01-01"},
        )

        assert source.metadata["query"] == "test query"
        assert source.metadata["timestamp"] == "2024-01-01"


class TestCardVersionDataclass:
    """Tests for CardVersion dataclass."""

    def test_card_version_is_dataclass(self):
        """CardVersion is a dataclass."""
        from local_deep_research.news.core.base_card import CardVersion

        assert is_dataclass(CardVersion)

    def test_card_version_initialization(self):
        """CardVersion initializes with required fields."""
        from local_deep_research.news.core.base_card import CardVersion
        from datetime import datetime

        version = CardVersion(
            version_id="v1",
            created_at=datetime.now(),
            content={"result": "test"},
            query_used="test query",
        )

        assert version.version_id == "v1"
        assert version.query_used == "test query"
        assert version.content == {"result": "test"}

    def test_card_version_optional_search_strategy(self):
        """CardVersion has optional search_strategy."""
        from local_deep_research.news.core.base_card import CardVersion
        from datetime import datetime

        version = CardVersion(
            version_id="v1",
            created_at=datetime.now(),
            content={},
            query_used="test",
        )

        assert version.search_strategy is None

    def test_card_version_generates_id_if_empty(self):
        """CardVersion generates ID if provided ID is empty."""
        from local_deep_research.news.core.base_card import CardVersion
        from datetime import datetime

        version = CardVersion(
            version_id="",
            created_at=datetime.now(),
            content={},
            query_used="test",
        )

        assert version.version_id != ""
        assert len(version.version_id) > 0


class TestBaseCardClass:
    """Tests for BaseCard abstract class."""

    def test_base_card_is_abstract(self):
        """BaseCard is an abstract class."""
        from local_deep_research.news.core.base_card import BaseCard

        assert issubclass(BaseCard, ABC)

    def test_base_card_is_dataclass(self):
        """BaseCard is a dataclass."""
        from local_deep_research.news.core.base_card import BaseCard

        assert is_dataclass(BaseCard)


class TestConcreteCard:
    """Tests using a concrete implementation of BaseCard."""

    @pytest.fixture
    def card_source(self):
        """Create a card source."""
        from local_deep_research.news.core.base_card import CardSource

        return CardSource(type="test")

    @pytest.fixture
    def concrete_card_class(self):
        """Create a concrete card class."""
        from local_deep_research.news.core.base_card import BaseCard

        class TestCard(BaseCard):
            def get_card_type(self):
                return "test"

            def to_dict(self):
                return {"id": self.id, "topic": self.topic}

        return TestCard

    def test_card_initialization(self, concrete_card_class, card_source):
        """Card initializes with required fields."""
        card = concrete_card_class(
            topic="Test Topic",
            source=card_source,
            user_id="user123",
        )

        assert card.topic == "Test Topic"
        assert card.source is card_source
        assert card.user_id == "user123"

    def test_card_generates_id(self, concrete_card_class, card_source):
        """Card generates ID when not provided."""
        card = concrete_card_class(
            topic="Test Topic",
            source=card_source,
            user_id="user123",
        )

        assert card.id is not None
        assert len(card.id) > 0

    def test_card_uses_provided_id(self, concrete_card_class, card_source):
        """Card uses provided card_id."""
        card = concrete_card_class(
            topic="Test Topic",
            source=card_source,
            user_id="user123",
            card_id="custom-id-123",
        )

        assert card.id == "custom-id-123"

    def test_card_timestamps_generated(self, concrete_card_class, card_source):
        """Card generates timestamps on creation."""
        card = concrete_card_class(
            topic="Test Topic",
            source=card_source,
            user_id="user123",
        )

        assert card.created_at is not None
        assert card.updated_at is not None

    def test_card_interaction_defaults(self, concrete_card_class, card_source):
        """Card has default interaction values."""
        card = concrete_card_class(
            topic="Test Topic",
            source=card_source,
            user_id="user123",
        )

        assert card.interaction["votes_up"] == 0
        assert card.interaction["votes_down"] == 0
        assert card.interaction["views"] == 0
        assert card.interaction["shares"] == 0

    def test_card_empty_versions_list(self, concrete_card_class, card_source):
        """Card has empty versions list initially."""
        card = concrete_card_class(
            topic="Test Topic",
            source=card_source,
            user_id="user123",
        )

        assert card.versions == []

    def test_card_optional_parent_id(self, concrete_card_class, card_source):
        """Card has optional parent_card_id."""
        card = concrete_card_class(
            topic="Test Topic",
            source=card_source,
            user_id="user123",
            parent_card_id="parent-123",
        )

        assert card.parent_card_id == "parent-123"

    def test_card_default_metadata(self, concrete_card_class, card_source):
        """Card has empty default metadata."""
        card = concrete_card_class(
            topic="Test Topic",
            source=card_source,
            user_id="user123",
        )

        assert card.metadata == {}

    def test_card_custom_metadata(self, concrete_card_class, card_source):
        """Card accepts custom metadata."""
        card = concrete_card_class(
            topic="Test Topic",
            source=card_source,
            user_id="user123",
            metadata={"key": "value"},
        )

        assert card.metadata == {"key": "value"}


class TestCardProgressCallback:
    """Tests for card progress callback."""

    @pytest.fixture
    def card_source(self):
        """Create a card source."""
        from local_deep_research.news.core.base_card import CardSource

        return CardSource(type="test")

    @pytest.fixture
    def concrete_card_class(self):
        """Create a concrete card class."""
        from local_deep_research.news.core.base_card import BaseCard

        class TestCard(BaseCard):
            def get_card_type(self):
                return "test"

            def to_dict(self):
                return {"id": self.id, "topic": self.topic}

        return TestCard

    def test_card_progress_callback_initially_none(
        self, concrete_card_class, card_source
    ):
        """Card progress_callback is None initially."""
        card = concrete_card_class(
            topic="Test",
            source=card_source,
            user_id="user123",
        )

        assert card.progress_callback is None

    def test_card_set_progress_callback(self, concrete_card_class, card_source):
        """Card can set progress callback."""
        card = concrete_card_class(
            topic="Test",
            source=card_source,
            user_id="user123",
        )

        callback = Mock()
        card.set_progress_callback(callback)

        assert card.progress_callback is callback
