"""Tests for CrewAI auto-instrumentation."""
from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime, timezone
from typing import Any
from unittest.mock import MagicMock, patch

import pytest

from fibinaci._testing.mock_client import MockFibinaci


@dataclass
class FakeAgent:
    role: str = "researcher"


@dataclass
class FakeTask:
    description: str = "research task"


@dataclass
class FakeCrewResult:
    token_usage: dict = None

    def __post_init__(self):
        if self.token_usage is None:
            self.token_usage = {"prompt_tokens": 500, "completion_tokens": 200}


class TestCrewAIInstrumentation:
    @pytest.fixture
    def setup_crewai(self):
        mod = MagicMock()
        crew_cls = MagicMock()
        original_kickoff = MagicMock(return_value=FakeCrewResult())
        crew_cls.kickoff = original_kickoff
        crew_cls.kickoff_async = MagicMock()
        mod.Crew = crew_cls
        return mod, crew_cls, original_kickoff

    def test_instrument_patches_kickoff(self, setup_crewai, mock_fibinaci: MockFibinaci):
        mod, crew_cls, original_kickoff = setup_crewai
        with patch.dict("sys.modules", {"crewai": mod}):
            from fibinaci.instrumentation.crewai import CrewAIInstrumentor
            inst = CrewAIInstrumentor()
            inst.instrument()
            assert crew_cls.kickoff is not original_kickoff
            inst.uninstrument()

    def test_extract_crew_info(self, mock_fibinaci: MockFibinaci):
        from fibinaci.instrumentation.crewai import _extract_crew_info

        crew = MagicMock()
        crew.agents = [FakeAgent(role="researcher"), FakeAgent(role="writer")]
        crew.tasks = [FakeTask(), FakeTask(), FakeTask()]
        crew.process = "sequential"

        info = _extract_crew_info(crew)
        assert info["agent_count"] == 2
        assert info["task_count"] == 3
        assert info["process"] == "sequential"
        assert info["agents"] == ["researcher", "writer"]

    def test_extract_crew_info_empty(self, mock_fibinaci: MockFibinaci):
        from fibinaci.instrumentation.crewai import _extract_crew_info

        crew = MagicMock()
        crew.agents = []
        crew.tasks = []
        crew.process = "hierarchical"

        info = _extract_crew_info(crew)
        assert info["agent_count"] == 0
        assert info["task_count"] == 0
