"""Tests for TeachingAssistantAgent lesson context functionality."""

import pytest
from unittest.mock import Mock

from agenai.agents.teaching_assistant import TeachingAssistantAgent
from agenai.agent.llm import LLMResponse


# =============================================================================
# Mock LLM Provider
# =============================================================================

class MockLLMProvider:
    """Mock LLM for testing."""

    def __init__(self, response_text: str = "Mock response"):
        self.response_text = response_text
        self.call_count = 0

    def chat(self, messages, system=None, tools=None, max_tokens=4096, temperature=0.7):
        self.call_count += 1
        return LLMResponse(text=self.response_text, tool_calls=[])


# =============================================================================
# _build_lesson_context_prompt Tests
# =============================================================================

class TestBuildLessonContextPrompt:
    """Tests for TeachingAssistantAgent._build_lesson_context_prompt() method."""

    def test_returns_empty_string_when_no_context(self):
        """Should return empty string when lesson_context is None."""
        llm = MockLLMProvider()
        agent = TeachingAssistantAgent(llm=llm, lesson_context=None)

        result = agent._build_lesson_context_prompt()

        assert result == ""

    def test_returns_empty_string_when_context_is_empty_dict(self):
        """Should return minimal output for empty context dict."""
        llm = MockLLMProvider()
        agent = TeachingAssistantAgent(llm=llm, lesson_context={})

        result = agent._build_lesson_context_prompt()

        # Should still have headers but minimal content
        assert "## Current Lesson Context" in result

    def test_includes_lesson_title(self):
        """Should include lesson title in prompt."""
        llm = MockLLMProvider()
        lesson_context = {
            "lesson": {
                "title": "Introduction to Variables",
                "difficulty": "beginner",
            }
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        result = agent._build_lesson_context_prompt()

        assert "Introduction to Variables" in result

    def test_includes_lesson_difficulty(self):
        """Should include lesson difficulty in prompt."""
        llm = MockLLMProvider()
        lesson_context = {
            "lesson": {
                "title": "Test",
                "difficulty": "advanced",
            }
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        result = agent._build_lesson_context_prompt()

        assert "advanced" in result

    def test_includes_lesson_description(self):
        """Should include lesson description when provided."""
        llm = MockLLMProvider()
        lesson_context = {
            "lesson": {
                "title": "Test",
                "difficulty": "beginner",
                "description": "Learn the basics of Python variables",
            }
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        result = agent._build_lesson_context_prompt()

        assert "Learn the basics of Python variables" in result

    def test_includes_section_info(self):
        """Should include current section information."""
        llm = MockLLMProvider()
        lesson_context = {
            "current_section": {
                "title": "What is a Variable?",
                "type": "concept",
            }
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        result = agent._build_lesson_context_prompt()

        assert "What is a Variable?" in result
        assert "concept" in result

    def test_includes_section_content(self):
        """Should include section content when provided."""
        llm = MockLLMProvider()
        lesson_context = {
            "current_section": {
                "title": "Test",
                "type": "concept",
                "content": "A variable is a container for storing data values.",
            }
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        result = agent._build_lesson_context_prompt()

        assert "A variable is a container" in result

    def test_truncates_long_content(self):
        """Should truncate very long section content."""
        llm = MockLLMProvider()
        long_content = "A" * 1000  # Content longer than 500 chars
        lesson_context = {
            "current_section": {
                "title": "Test",
                "type": "concept",
                "content": long_content,
            }
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        result = agent._build_lesson_context_prompt()

        # Should be truncated with ellipsis
        assert "..." in result
        # Should not contain full content
        assert long_content not in result

    def test_includes_section_instruction(self):
        """Should include section instruction when provided."""
        llm = MockLLMProvider()
        lesson_context = {
            "current_section": {
                "title": "Try It",
                "type": "interactive",
                "instruction": "Create a variable named 'x' with value 5",
            }
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        result = agent._build_lesson_context_prompt()

        assert "Create a variable named 'x' with value 5" in result

    def test_includes_student_age_group(self):
        """Should include student age group."""
        llm = MockLLMProvider()
        lesson_context = {
            "student": {
                "age_group": "teen",
            }
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        result = agent._build_lesson_context_prompt()

        assert "teen" in result
        assert "Age Group" in result

    def test_includes_student_interests(self):
        """Should include student interests."""
        llm = MockLLMProvider()
        lesson_context = {
            "student": {
                "age_group": "young_adult",
                "interests": ["gaming", "web development"],
            }
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        result = agent._build_lesson_context_prompt()

        assert "gaming" in result
        assert "web development" in result
        assert "Interests" in result

    def test_handles_empty_interests(self):
        """Should handle empty interests list."""
        llm = MockLLMProvider()
        lesson_context = {
            "student": {
                "age_group": "adult",
                "interests": [],
            }
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        result = agent._build_lesson_context_prompt()

        # Should not crash, should include age group
        assert "adult" in result

    def test_includes_progress_status(self):
        """Should include student progress status."""
        llm = MockLLMProvider()
        lesson_context = {
            "progress": {
                "status": "in_progress",
            }
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        result = agent._build_lesson_context_prompt()

        assert "in_progress" in result
        assert "Status" in result

    def test_includes_quiz_score(self):
        """Should include quiz score when available."""
        llm = MockLLMProvider()
        lesson_context = {
            "progress": {
                "status": "completed",
                "score": 85,
            }
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        result = agent._build_lesson_context_prompt()

        assert "85" in result
        assert "Score" in result or "%" in result

    def test_handles_none_score(self):
        """Should handle None quiz score gracefully."""
        llm = MockLLMProvider()
        lesson_context = {
            "progress": {
                "status": "in_progress",
                "score": None,
            }
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        result = agent._build_lesson_context_prompt()

        # Should not crash, should include status
        assert "in_progress" in result

    def test_includes_teaching_guidelines(self):
        """Should include teaching guidelines section."""
        llm = MockLLMProvider()
        lesson_context = {
            "lesson": {"title": "Test", "difficulty": "beginner"},
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        result = agent._build_lesson_context_prompt()

        assert "Teaching Guidelines" in result

    def test_full_context_includes_all_sections(self):
        """Should include all sections when full context is provided."""
        llm = MockLLMProvider()
        lesson_context = {
            "lesson": {
                "id": 1,
                "title": "Python Variables",
                "difficulty": "beginner",
                "description": "Learn about variables",
            },
            "current_section": {
                "index": 0,
                "type": "concept",
                "title": "What is a Variable?",
                "content": "A variable stores data",
                "instruction": "Read and understand",
            },
            "student": {
                "age": 16,
                "age_group": "teen",
                "interests": ["gaming", "ai"],
            },
            "progress": {
                "status": "in_progress",
                "score": None,
            },
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        result = agent._build_lesson_context_prompt()

        # Verify all major sections present
        assert "## Current Lesson Context" in result
        assert "Python Variables" in result
        assert "beginner" in result
        assert "What is a Variable?" in result
        assert "concept" in result
        assert "teen" in result
        assert "gaming" in result
        assert "in_progress" in result
        assert "Teaching Guidelines" in result


class TestSystemPromptWithLessonContext:
    """Tests for get_system_prompt() with lesson context."""

    def test_system_prompt_includes_lesson_context(self):
        """Should include lesson context in system prompt."""
        llm = MockLLMProvider()
        lesson_context = {
            "lesson": {"title": "Test Lesson", "difficulty": "intermediate"},
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        prompt = agent.get_system_prompt()

        assert "Test Lesson" in prompt
        assert "intermediate" in prompt

    def test_system_prompt_without_lesson_context(self):
        """Should work without lesson context."""
        llm = MockLLMProvider()
        agent = TeachingAssistantAgent(llm=llm, lesson_context=None)

        prompt = agent.get_system_prompt()

        # Should still have base prompt content
        assert "teach" in prompt.lower() or "assistant" in prompt.lower()
        # Should NOT have lesson context headers
        assert "## Current Lesson Context" not in prompt


class TestAgentWithLessonContext:
    """Tests for agent behavior with lesson context."""

    def test_agent_stores_lesson_context(self):
        """Agent should store lesson context for use."""
        llm = MockLLMProvider()
        lesson_context = {
            "lesson": {"title": "Test", "difficulty": "beginner"},
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        assert agent._lesson_context == lesson_context

    def test_agent_with_none_lesson_context(self):
        """Agent should handle None lesson context."""
        llm = MockLLMProvider()
        agent = TeachingAssistantAgent(llm=llm, lesson_context=None)

        assert agent._lesson_context is None
        # Should not crash when getting system prompt
        prompt = agent.get_system_prompt()
        assert prompt is not None

    def test_agent_run_with_lesson_context(self):
        """Agent should run successfully with lesson context."""
        llm = MockLLMProvider("Here's an explanation tailored to your lesson...")
        lesson_context = {
            "lesson": {"title": "Variables", "difficulty": "beginner"},
            "student": {"age_group": "teen", "interests": ["gaming"]},
        }
        agent = TeachingAssistantAgent(llm=llm, lesson_context=lesson_context)

        result = agent.run("Explain this section")

        assert result.success
        assert result.output == "Here's an explanation tailored to your lesson..."

    def test_difficulty_level_preserved_with_lesson_context(self):
        """Should preserve difficulty_level setting alongside lesson context."""
        llm = MockLLMProvider()
        lesson_context = {
            "lesson": {"title": "Test", "difficulty": "beginner"},
        }
        agent = TeachingAssistantAgent(
            llm=llm,
            lesson_context=lesson_context,
            difficulty_level="advanced",
        )

        assert agent.difficulty_level == "advanced"
        prompt = agent.get_system_prompt()
        assert "advanced" in prompt.lower()
