#!/usr/bin/env python3
"""
Practical integration test for Fast-CrewAI.

This test creates actual CrewAI agents, tasks, and crews to verify that:
1. The shim activates correctly
2. All patches work with real CrewAI workflows
3. Tools, tasks, and memory components function properly
4. No API compatibility issues exist

This is a real-world test that mimics actual CrewAI usage.
"""

import os
import sys

import pytest

# Add current directory to path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

# Check if CrewAI is available - skip entire module if not
try:
    import crewai  # noqa: F401

    CREWAI_AVAILABLE = True
except ImportError:
    CREWAI_AVAILABLE = False

# Skip entire module if CrewAI is not installed
pytestmark = pytest.mark.skipif(
    not CREWAI_AVAILABLE, reason="CrewAI not installed - skipping integration tests"
)


@pytest.mark.integration
class TestFastCrewAIIntegration:
    """Integration tests for Fast-CrewAI with real CrewAI components."""

    def test_shim_activation(self):
        """Test that the shim activates correctly."""
        import fast_crewai.shim  # noqa: F401

        # If we get here, the shim activated successfully
        assert True

    def test_acceleration_status(self):
        """Test that acceleration status can be retrieved."""
        from fast_crewai import get_acceleration_status

        status = get_acceleration_status()
        assert isinstance(status, dict)
        assert "available" in status or "components" in status

    def test_crewai_import_after_shim(self):
        """Test that CrewAI can be imported after shim activation."""
        from crewai import Agent, Crew, Task
        from crewai.tools import tool

        import fast_crewai.shim  # noqa: F401

        assert Agent is not None
        assert Task is not None
        assert Crew is not None
        assert tool is not None

    def test_class_patching(self):
        """Test that CrewAI classes are properly patched."""
        from crewai.crew import Crew as CrewClass
        from crewai.task import Task as TaskClass
        from crewai.tools.base_tool import BaseTool

        import fast_crewai.shim  # noqa: F401

        # Classes should be accessible
        assert BaseTool is not None
        assert TaskClass is not None
        assert CrewClass is not None

    def test_tool_creation(self):
        """Test that tools can be created with the shim active."""
        from crewai.tools import tool

        import fast_crewai.shim  # noqa: F401

        @tool
        def calculate_sum(a: int, b: int) -> int:
            """Calculate the sum of two numbers."""
            return a + b

        assert hasattr(calculate_sum, "name")
        assert calculate_sum.name is not None

    def test_tool_execution(self):
        """Test that tools can be executed."""
        from crewai.tools import tool

        import fast_crewai.shim  # noqa: F401

        @tool
        def calculate_sum(a: int, b: int) -> int:
            """Calculate the sum of two numbers."""
            return a + b

        # Try different invocation patterns
        if hasattr(calculate_sum, "_run"):
            calculate_sum._run(5, 3)
        elif hasattr(calculate_sum, "run"):
            calculate_sum.run(a=5, b=3)
        elif hasattr(calculate_sum, "func"):
            calculate_sum.func(5, 3)

        # Tool execution may require different patterns based on CrewAI version
        # This test just verifies the tool was created successfully
        assert calculate_sum is not None

    def test_memory_components(self):
        """Test that memory components work correctly."""
        from fast_crewai.memory import AcceleratedMemoryStorage

        memory = AcceleratedMemoryStorage(embedder=None)
        assert memory is not None
        assert hasattr(memory, "implementation")

    def test_serialization(self):
        """Test that serialization components work correctly."""
        from fast_crewai.serialization import AgentMessage

        msg = AgentMessage(
            id="test-1",
            sender="agent1",
            recipient="agent2",
            content="Hello, World!",
            timestamp=1234567890,
        )

        json_str = msg.to_json()
        assert json_str is not None
        assert "Hello, World!" in json_str

        msg2 = AgentMessage.from_json(json_str)
        assert msg2.content == "Hello, World!"
        assert msg2.sender == "agent1"
        assert msg2.recipient == "agent2"


@pytest.mark.integration
@pytest.mark.slow
class TestFastCrewAIWithLLM:
    """Integration tests that require an LLM API key."""

    @pytest.fixture
    def api_key_available(self):
        """Check if API key is available."""
        return os.environ.get("OPENAI_API_KEY") is not None

    def test_agent_creation(self, api_key_available):
        """Test agent creation (requires API key)."""
        if not api_key_available:
            pytest.skip("OPENAI_API_KEY not set")

        from crewai import Agent
        from crewai.tools import tool

        import fast_crewai.shim  # noqa: F401

        @tool
        def calculate_sum(a: int, b: int) -> int:
            """Calculate the sum of two numbers."""
            return a + b

        agent = Agent(
            role="Math Assistant",
            goal="Help with mathematical calculations",
            backstory="You are a helpful assistant that performs calculations.",
            tools=[calculate_sum],
            verbose=False,
            llm="gpt-4o-mini",
        )

        assert agent is not None
        assert agent.role == "Math Assistant"

    def test_task_creation(self, api_key_available):
        """Test task creation (requires API key)."""
        if not api_key_available:
            pytest.skip("OPENAI_API_KEY not set")

        from crewai import Agent, Task
        from crewai.tools import tool

        import fast_crewai.shim  # noqa: F401

        @tool
        def calculate_sum(a: int, b: int) -> int:
            """Calculate the sum of two numbers."""
            return a + b

        agent = Agent(
            role="Math Assistant",
            goal="Help with mathematical calculations",
            backstory="You are a helpful assistant that performs calculations.",
            tools=[calculate_sum],
            verbose=False,
            llm="gpt-4o-mini",
        )

        task = Task(
            description="Calculate the sum of 10 and 20",
            expected_output="The sum of 10 and 20",
            agent=agent,
        )

        assert task is not None
        assert "sum" in task.description.lower()

    def test_crew_creation(self, api_key_available):
        """Test crew creation (requires API key)."""
        if not api_key_available:
            pytest.skip("OPENAI_API_KEY not set")

        from crewai import Agent, Crew, Task
        from crewai.tools import tool

        import fast_crewai.shim  # noqa: F401

        @tool
        def calculate_sum(a: int, b: int) -> int:
            """Calculate the sum of two numbers."""
            return a + b

        agent = Agent(
            role="Math Assistant",
            goal="Help with mathematical calculations",
            backstory="You are a helpful assistant that performs calculations.",
            tools=[calculate_sum],
            verbose=False,
            llm="gpt-4o-mini",
        )

        task = Task(
            description="Calculate the sum of 10 and 20",
            expected_output="The sum of 10 and 20",
            agent=agent,
        )

        crew = Crew(agents=[agent], tasks=[task], verbose=False)

        assert crew is not None
        assert len(crew.agents) == 1
        assert len(crew.tasks) == 1
