"""Tests for the IntelligenceManager's clarification integration."""
import pytest
from datetime import datetime
from unittest.mock import Mock, patch, AsyncMock
from bat_genie.intelligence_manager import IntelligenceManager, IntelligenceConfig
from bat_genie.clarification_manager import ClarificationQuestion

@pytest.fixture
def mock_config():
    """Create a test configuration."""
    return IntelligenceConfig(
        workspace_root="/test/workspace",
        cache_dir=".cursor/cache",
        learning_db_path=".cursor/learning.json",
        context_db_path=".cursor/context_db.json",
        enable_auto_learning=True,
        enable_goal_tracking=True,
        enable_resource_caching=True,
        enable_clarification=True
    )

@pytest.fixture
def mock_managers():
    """Create mock component managers."""
    context_manager = Mock()
    goal_manager = Mock()
    resource_manager = Mock()
    learning_manager = Mock()
    clarification_manager = Mock()
    
    # Set up context manager mock
    context_manager.get_project_context.return_value = {
        'name': 'test_project',
        'description': 'Test project',
        'goals': [],
        'success_criteria': [],
        'current_phase': 'development',
        'technologies': {},
        'dependencies': {},
        'last_updated': datetime.now().isoformat()
    }
    
    # Set up goal manager mock
    goal_manager.get_active_goals.return_value = []
    
    # Set up learning manager mock
    learning_manager.find_similar_cases.return_value = []
    
    # Set up resource manager mock
    resource_manager.get_resources_by_tag.return_value = []
    
    return {
        'context_manager': context_manager,
        'goal_manager': goal_manager,
        'resource_manager': resource_manager,
        'learning_manager': learning_manager,
        'clarification_manager': clarification_manager
    }

@pytest.fixture
def intelligence_manager(mock_config, mock_managers):
    """Create an IntelligenceManager instance for testing."""
    with patch('bat_genie.intelligence_manager.ContextManager') as context_mock, \
         patch('bat_genie.intelligence_manager.GoalManager') as goal_mock, \
         patch('bat_genie.intelligence_manager.ResourceManager') as resource_mock, \
         patch('bat_genie.intelligence_manager.LearningManager') as learning_mock, \
         patch('bat_genie.intelligence_manager.ClarificationManager') as clarification_mock:
        
        context_mock.return_value = mock_managers['context_manager']
        goal_mock.return_value = mock_managers['goal_manager']
        resource_mock.return_value = mock_managers['resource_manager']
        learning_mock.return_value = mock_managers['learning_manager']
        clarification_mock.return_value = mock_managers['clarification_manager']
        
        manager = IntelligenceManager(mock_config)
        return manager

@pytest.mark.asyncio
async def test_analyze_request_needs_clarification(intelligence_manager, mock_managers):
    """Test analyzing a request that needs clarification."""
    # Set up mock clarification response
    mock_managers['clarification_manager'].analyze_request.return_value = {
        'required_clarifications': ['objectives', 'scope'],
        'suggested_questions': [
            ClarificationQuestion(
                id="q1",
                question="What are your objectives?",
                context="make it better",
                category="objective",
                priority=1,
                status="pending",
                answer=None,
                created_at=datetime.now().isoformat(),
                updated_at=datetime.now().isoformat()
            )
        ]
    }
    
    analysis = await intelligence_manager.analyze_request("make it better")
    
    assert analysis['clarification_needed'] is True
    assert len(analysis['clarification_questions']) == 1
    assert analysis['clarification_questions'][0]['question'] == "What are your objectives?"

@pytest.mark.asyncio
async def test_analyze_request_no_clarification_needed(intelligence_manager, mock_managers):
    """Test analyzing a request that doesn't need clarification."""
    # Set up mock clarification response
    mock_managers['clarification_manager'].analyze_request.return_value = {
        'required_clarifications': [],
        'suggested_questions': []
    }
    
    analysis = await intelligence_manager.analyze_request(
        "Our goal is to optimize database performance for better user experience"
    )
    
    assert analysis['clarification_needed'] is False
    assert len(analysis['clarification_questions']) == 0
    assert 'context' in analysis
    assert 'relevant_goals' in analysis
    assert 'learned_patterns' in analysis
    assert 'resources' in analysis

@pytest.mark.asyncio
async def test_execute_action_needs_clarification(intelligence_manager, mock_managers):
    """Test executing an action that needs clarification."""
    # Set up mock clarification response
    mock_managers['clarification_manager'].analyze_request.return_value = {
        'required_clarifications': ['technical_constraints'],
        'suggested_questions': [
            ClarificationQuestion(
                id="q1",
                question="What are the technical constraints?",
                context="optimize database",
                category="technical",
                priority=1,
                status="pending",
                answer=None,
                created_at=datetime.now().isoformat(),
                updated_at=datetime.now().isoformat()
            )
        ]
    }
    
    result = await intelligence_manager.execute_action(
        "optimize database",
        {'target': 'performance'}
    )
    
    assert result['clarification_needed'] is True
    assert len(result['clarification_questions']) == 1
    assert result['success'] is False
    assert result['output'] is None

@pytest.mark.asyncio
async def test_execute_action_no_clarification_needed(intelligence_manager, mock_managers):
    """Test executing an action that doesn't need clarification."""
    # Set up mock clarification response
    mock_managers['clarification_manager'].analyze_request.return_value = {
        'required_clarifications': [],
        'suggested_questions': []
    }
    
    result = await intelligence_manager.execute_action(
        "optimize database",
        {
            'target': 'performance',
            'constraints': {'response_time': '100ms'}
        }
    )
    
    assert result['clarification_needed'] is False
    assert len(result['clarification_questions']) == 0
    assert result['success'] is True
    assert result['output'] is not None

def test_record_clarification(intelligence_manager, mock_managers):
    """Test recording a clarification answer."""
    intelligence_manager.record_clarification(
        "q1",
        "Response time should be under 100ms"
    )
    
    # Verify clarification was recorded
    mock_managers['clarification_manager'].record_answer.assert_called_once_with(
        "q1",
        "Response time should be under 100ms"
    )
    
    # Verify insight was added
    mock_managers['context_manager'].add_insight.assert_called_once()

def test_get_intelligence_status_includes_clarifications(intelligence_manager, mock_managers):
    """Test that intelligence status includes clarification information."""
    # Set up mock for pending questions
    mock_managers['clarification_manager'].questions = {
        'q1': Mock(status="pending"),
        'q2': Mock(status="answered")
    }
    
    # Set up mock for cache index
    mock_managers['resource_manager'].cache_index = {}
    
    status = intelligence_manager.get_intelligence_status()
    
    assert 'pending_clarifications' in status
    assert status['pending_clarifications'] == 1 