"""Tests for BaseCard pure helper methods.

Tests cover:
- _calculate_impact: scoring based on findings and sources count
- _extract_headline: multi-field fallback extraction
- _extract_summary: multi-field fallback extraction
- _extract_topics: topic extraction with keyword fallback
- _extract_entities: entity extraction with default structure
"""

import pytest

from local_deep_research.news.core.base_card import CardSource, NewsCard


# ---------------------------------------------------------------------------
# Fixtures
# ---------------------------------------------------------------------------


@pytest.fixture()
def card():
    """Build a minimal NewsCard for testing helper methods."""
    return NewsCard(
        topic="Test Topic",
        source=CardSource(type="news_item"),
        user_id="user-1",
    )


# ===================================================================
# _calculate_impact
# ===================================================================


class TestCalculateImpact:
    """Tests for BaseCard._calculate_impact()."""

    def test_empty_result_returns_base_score(self, card):
        assert card._calculate_impact({}) == 5

    def test_findings_increase_score(self, card):
        result = {"findings": [f"f{i}" for i in range(10)]}
        score = card._calculate_impact(result)
        assert score == 7  # 5 + 10//5 = 7

    def test_sources_increase_score(self, card):
        result = {"sources": [f"s{i}" for i in range(9)]}
        score = card._calculate_impact(result)
        assert score == 8  # 5 + 9//3 = 8

    def test_combined_findings_and_sources(self, card):
        result = {
            "findings": [f"f{i}" for i in range(5)],
            "sources": [f"s{i}" for i in range(6)],
        }
        score = card._calculate_impact(result)
        assert score == 8  # 5 + 5//5 + 6//3 = 8

    def test_max_score_capped_at_10(self, card):
        result = {
            "findings": list(range(100)),
            "sources": list(range(100)),
        }
        assert card._calculate_impact(result) == 10

    def test_min_score_is_1(self, card):
        # Even with no findings/sources, min(10, 5+0+0)=5, max(1,5)=5
        # Score can't go below 1 by design
        assert card._calculate_impact({}) >= 1


# ===================================================================
# _extract_headline
# ===================================================================


class TestExtractHeadline:
    """Tests for BaseCard._extract_headline()."""

    def test_headline_field_preferred(self, card):
        result = {"headline": "Breaking News", "title": "Alt Title"}
        assert card._extract_headline(result) == "Breaking News"

    def test_title_fallback(self, card):
        result = {"title": "Article Title"}
        assert card._extract_headline(result) == "Article Title"

    def test_query_fallback_truncated(self, card):
        long_query = "x" * 200
        result = {"query": long_query}
        headline = card._extract_headline(result)
        assert len(headline) == 100

    def test_empty_result_returns_empty(self, card):
        assert card._extract_headline({}) == ""

    def test_headline_none_falls_through(self, card):
        result = {"headline": None, "title": "Fallback"}
        assert card._extract_headline(result) == "Fallback"

    def test_all_none_falls_to_query(self, card):
        result = {"headline": None, "title": None, "query": "my query"}
        assert card._extract_headline(result) == "my query"


# ===================================================================
# _extract_summary
# ===================================================================


class TestExtractSummary:
    """Tests for BaseCard._extract_summary()."""

    def test_summary_field_preferred(self, card):
        result = {"summary": "Brief summary", "current_knowledge": "Knowledge"}
        assert card._extract_summary(result) == "Brief summary"

    def test_current_knowledge_fallback(self, card):
        result = {"current_knowledge": "Deep knowledge"}
        assert card._extract_summary(result) == "Deep knowledge"

    def test_formatted_findings_fallback_truncated(self, card):
        long_findings = "z" * 1000
        result = {"formatted_findings": long_findings}
        summary = card._extract_summary(result)
        assert len(summary) == 500

    def test_empty_result_returns_empty(self, card):
        assert card._extract_summary({}) == ""


# ===================================================================
# _extract_topics
# ===================================================================


class TestExtractTopics:
    """Tests for BaseCard._extract_topics()."""

    def test_explicit_topics_returned(self, card):
        result = {"topics": ["AI", "Climate"]}
        assert card._extract_topics(result) == ["AI", "Climate"]

    def test_query_keyword_fallback(self, card):
        result = {"query": "global climate change effects"}
        topics = card._extract_topics(result)
        # Words > 4 chars: global, climate, change, effects
        assert "global" in topics
        assert "climate" in topics

    def test_query_short_words_excluded(self, card):
        result = {"query": "how is the AI doing today"}
        topics = card._extract_topics(result)
        # "how", "is", "the", "AI" (2 chars), "doing" (5), "today" (5)
        assert "doing" in topics
        assert "today" in topics

    def test_max_five_topics_from_query(self, card):
        result = {
            "query": "these words are all quite longer than four characters each"
        }
        topics = card._extract_topics(result)
        assert len(topics) <= 5

    def test_empty_result_returns_empty(self, card):
        assert card._extract_topics({}) == []

    def test_empty_topics_triggers_query_fallback(self, card):
        result = {"topics": [], "query": "quantum computing advances"}
        topics = card._extract_topics(result)
        assert len(topics) > 0


# ===================================================================
# _extract_entities
# ===================================================================


class TestExtractEntities:
    """Tests for BaseCard._extract_entities()."""

    def test_explicit_entities_returned(self, card):
        entities = {
            "people": ["Alice"],
            "places": ["NYC"],
            "organizations": ["UN"],
        }
        result = {"entities": entities}
        assert card._extract_entities(result) == entities

    def test_default_entities_structure(self, card):
        result = card._extract_entities({})
        assert result == {"people": [], "places": [], "organizations": []}
