"""
Extended tests for Question Generators - Follow-up and sub-question generation.

Tests cover:
- Standard question generation
- Follow-up question generation
- Sub-question decomposition
- Context-aware query generation
- Edge cases and error handling
"""


class TestStandardQuestionGeneration:
    """Tests for StandardQuestionGenerator."""

    def test_generate_questions_prompt_structure(self):
        """Prompt should have correct structure for question generation."""
        query = "What is quantum computing?"
        current_knowledge = "Quantum computing uses qubits..."

        prompt = f"""Based on the following query and current knowledge, generate follow-up questions:

Query: {query}
Current Knowledge: {current_knowledge}

Generate 2 follow-up questions that would help deepen understanding."""

        assert "quantum computing" in prompt
        assert "qubits" in prompt

    def test_default_questions_per_iteration(self):
        """Default should be 2 questions per iteration."""
        default_count = 2
        assert default_count == 2

    def test_custom_questions_per_iteration(self):
        """Should support custom question count."""
        custom_count = 5
        assert custom_count == 5


class TestSubQuestionGeneration:
    """Tests for sub-question generation."""

    def test_generate_sub_questions_from_complex_query(self):
        """Should break complex queries into sub-questions."""
        main_query = (
            "How does blockchain ensure security and what are its applications?"
        )

        # Simulated sub-question decomposition
        sub_questions = [
            "How does blockchain ensure security?",
            "What are the applications of blockchain?",
        ]

        assert len(sub_questions) == 2
        assert "security" in sub_questions[0]
        assert "applications" in sub_questions[1]
        # Sub-questions should relate to main query
        assert "blockchain" in main_query

    def test_simple_query_may_not_decompose(self):
        """Simple queries may not need decomposition."""
        simple_query = "What is Python?"

        # Simple query doesn't need decomposition
        sub_questions = [simple_query]

        assert len(sub_questions) == 1


class TestFollowUpQuestionGeneration:
    """Tests for follow-up question generation."""

    def test_followup_analyzes_knowledge_gaps(self):
        """Follow-up questions should address knowledge gaps."""
        current_knowledge = "We know X but not Y"

        requirements = [
            "Critically reflects on knowledge timeliness",
            "Identifies gaps in current knowledge",
            "Generates targeted follow-up questions",
        ]

        assert "gaps" in requirements[1]
        # Knowledge statement indicates what we don't know
        assert "not Y" in current_knowledge

    def test_followup_question_count(self):
        """Should generate specified number of follow-up questions."""
        num_questions = 3
        questions = [f"Question {i + 1}?" for i in range(num_questions)]

        assert len(questions) == 3


class TestContextualizedQueryGeneration:
    """Tests for contextualized query generation."""

    def test_simple_concatenation(self):
        """Simple generator concatenates context with query."""
        previous_context = "Previous findings show X"
        followup_query = "What about Y?"

        contextualized = f"{previous_context}\n\n{followup_query}"

        assert "Previous findings show X" in contextualized
        assert "What about Y?" in contextualized

    def test_preserves_exact_user_query(self):
        """Should preserve exact user query."""
        user_query = "provide data in a table"

        # Query should be preserved exactly
        assert user_query == "provide data in a table"

    def test_provides_full_context(self):
        """Should provide full context from previous research."""
        previous_research = {
            "findings": ["Finding 1", "Finding 2"],
            "sources": ["Source 1", "Source 2"],
        }
        followup_query = "More details?"

        context = f"Previous findings: {previous_research['findings']}\nQuery: {followup_query}"

        assert "Finding 1" in context
        assert "More details?" in context


class TestLLMFollowUpGeneration:
    """Tests for LLM-based follow-up question generation."""

    def test_llm_reformulation_placeholder(self):
        """LLM reformulation is placeholder for future implementation."""
        # Current implementation falls back to simple concatenation
        is_placeholder = True
        assert is_placeholder is True

    def test_generates_multiple_targeted_questions(self):
        """Should generate multiple targeted questions."""
        num_questions = 5
        questions = [f"Targeted question {i + 1}" for i in range(num_questions)]

        assert len(questions) == 5

    def test_analyzes_followup_in_context(self):
        """Should analyze follow-up query in context of past findings."""
        past_findings = "We found A, B, C"
        followup = "What about D?"

        analysis_context = {
            "past_findings": past_findings,
            "followup_query": followup,
        }

        assert analysis_context["past_findings"] == "We found A, B, C"


class TestQuestionQuality:
    """Tests for question quality requirements."""

    def test_questions_should_deepen_understanding(self):
        """Generated questions should deepen understanding."""
        requirements = [
            "Questions should deepen understanding",
            "Questions should address gaps",
            "Questions should be specific",
        ]

        assert "deepen understanding" in requirements[0]

    def test_questions_should_be_relevant(self):
        """Questions should be relevant to original query."""
        original_query = "machine learning"
        question = "How does supervised learning work?"

        # Question should relate to original query
        is_relevant = "learning" in question
        assert is_relevant is True
        # Both should contain the common topic
        assert "learning" in original_query


class TestPromptConstruction:
    """Tests for prompt construction."""

    def test_prompt_includes_query(self):
        """Prompt should include the original query."""
        query = "test query"
        prompt = f"Query: {query}"

        assert "test query" in prompt

    def test_prompt_includes_current_knowledge(self):
        """Prompt should include current knowledge state."""
        knowledge = "Current state of knowledge"
        prompt = f"Current Knowledge: {knowledge}"

        assert "Current state of knowledge" in prompt

    def test_prompt_specifies_question_count(self):
        """Prompt should specify number of questions to generate."""
        num_questions = 3
        prompt = f"Generate {num_questions} follow-up questions"

        assert "3" in prompt


class TestErrorHandling:
    """Tests for error handling in question generation."""

    def test_llm_error_handled_gracefully(self):
        """LLM errors should be handled gracefully."""
        try:
            raise Exception("LLM error")
        except Exception:
            questions = []  # Return empty on error

        assert questions == []

    def test_empty_knowledge_handled(self):
        """Should handle empty current knowledge."""
        current_knowledge = ""

        if not current_knowledge:
            knowledge_context = "No prior knowledge available"
        else:
            knowledge_context = current_knowledge

        assert knowledge_context == "No prior knowledge available"


class TestResponseParsing:
    """Tests for parsing question generation responses."""

    def test_extract_questions_from_numbered_list(self):
        """Should extract questions from numbered list."""
        response = """1. What is X?
2. How does Y work?
3. Why is Z important?"""

        questions = []
        for line in response.strip().split("\n"):
            # Remove numbering
            if line.strip():
                cleaned = line.strip()
                if cleaned[0].isdigit() and "." in cleaned:
                    cleaned = cleaned.split(".", 1)[1].strip()
                questions.append(cleaned)

        assert len(questions) == 3
        assert questions[0] == "What is X?"

    def test_extract_questions_from_bullet_list(self):
        """Should extract questions from bullet list."""
        response = """- What is X?
- How does Y work?"""

        questions = []
        for line in response.strip().split("\n"):
            if line.startswith("-"):
                questions.append(line[1:].strip())

        assert len(questions) == 2


class TestKnowledgeTimeliness:
    """Tests for knowledge timeliness reflection."""

    def test_reflects_on_knowledge_age(self):
        """Should reflect on timeliness of current knowledge."""
        requirements = """Critically reflects on knowledge timeliness.
Considers whether information may be outdated.
Generates questions about recent developments."""

        assert "timeliness" in requirements
        assert "outdated" in requirements

    def test_generates_update_questions(self):
        """Should generate questions about updates/changes."""
        sample_questions = [
            "Have there been recent updates to X?",
            "What are the latest developments in Y?",
        ]

        assert "recent" in sample_questions[0]
        assert "latest" in sample_questions[1]


class TestContextPreservation:
    """Tests for context preservation in queries."""

    def test_table_reference_preserved(self):
        """References like 'provide data in a table' should be preserved."""
        followup = "provide data in a table"
        previous_findings = "Found data A, B, C"

        # User's exact query should be preserved
        query = followup
        context = previous_findings

        assert query == "provide data in a table"
        assert "Found data" in context

    def test_pronoun_references_understood(self):
        """Pronoun references should be understood from context."""
        previous = "We discussed Python programming"
        followup = "What are its main features?"

        # 'its' refers to Python from context
        full_context = f"{previous}\n{followup}"

        assert "Python" in full_context
        assert "its main features" in full_context
