"""Unit tests for the Perplexity research agent using OpenRouter."""

import pytest
import asyncio
from unittest.mock import AsyncMock, MagicMock, patch
from datetime import datetime, timezone
from typing import Dict, Any

from src.services.protocols import ResearchQuery, ResearchResult
from src.services.research.service import OpenRouterResearchService
from src.services.research.config import ResearchConfig


class TestPerplexityResearchAgent:
    """Test suite for Perplexity sonar-reasoning-pro research agent."""

    @pytest.fixture
    def mock_openrouter_service(self):
        """Create a mock OpenRouter service."""
        service = AsyncMock(spec=OpenRouterResearchService)
        service.research = AsyncMock()
        service.get_available_models = MagicMock(return_value=[
            "perplexity/sonar-reasoning-pro",
            "perplexity/sonar-medium-online",
            "openai/gpt-4"
        ])
        return service

    @pytest.fixture
    def sample_sonar_query(self):
        """Create a sample query for sonar-reasoning-pro."""
        return ResearchQuery(
            query="What are the latest developments in AI reasoning models?",
            context="Focus on models like o1, o3, and reasoning capabilities",
            max_tokens=4000,
            temperature=0.1,
            model="perplexity/sonar-reasoning-pro"
        )

    @pytest.fixture
    def sample_sonar_result(self):
        """Create a sample result from sonar-reasoning-pro."""
        return ResearchResult(
            query="What are the latest developments in AI reasoning models?",
            answer="Recent developments include OpenAI's o1 model which demonstrates...",
            sources=[
                "https://arxiv.org/abs/2024.12345",
                "https://openai.com/blog/o1-reasoning"
            ],
            confidence_score=0.92,
            processing_time=3.2,
            model_used="perplexity/sonar-reasoning-pro",
            token_usage={
                "prompt_tokens": 200,
                "completion_tokens": 1200,
                "total_tokens": 1400
            }
        )

    @pytest.mark.asyncio
    async def test_sonar_research_execution(self, mock_openrouter_service, sample_sonar_query, sample_sonar_result):
        """Test sonar-reasoning-pro research execution."""
        mock_openrouter_service.research.return_value = sample_sonar_result
        
        result = await mock_openrouter_service.research(sample_sonar_query)
        
        mock_openrouter_service.research.assert_called_once_with(sample_sonar_query)
        assert result.model_used == "perplexity/sonar-reasoning-pro"
        assert result.confidence_score > 0.9  # Sonar should have high confidence
        assert len(result.sources) > 0

    def test_sonar_query_validation(self):
        """Test sonar-specific query validation."""
        query = ResearchQuery(
            query="Test reasoning query",
            model="perplexity/sonar-reasoning-pro",
            max_tokens=4000,
            temperature=0.1
        )
        
        assert query.model == "perplexity/sonar-reasoning-pro"
        assert query.max_tokens <= 4000  # Sonar limit
        assert 0.0 <= query.temperature <= 1.0

    def test_sonar_result_quality(self, sample_sonar_result):
        """Test sonar result quality metrics."""
        assert sample_sonar_result.confidence_score >= 0.8  # High confidence expected
        assert sample_sonar_result.processing_time < 10.0  # Reasonable speed
        assert len(sample_sonar_result.sources) >= 1  # Should have sources
        assert sample_sonar_result.token_usage["total_tokens"] > 0

    @pytest.mark.asyncio
    async def test_sonar_error_handling(self, mock_openrouter_service, sample_sonar_query):
        """Test sonar error handling."""
        mock_openrouter_service.research.side_effect = Exception("OpenRouter API Error")
        
        with pytest.raises(Exception, match="OpenRouter API Error"):
            await mock_openrouter_service.research(sample_sonar_query)

    def test_sonar_model_availability(self, mock_openrouter_service):
        """Test sonar model availability."""
        models = mock_openrouter_service.get_available_models()
        
        assert "perplexity/sonar-reasoning-pro" in models
        assert "perplexity/sonar-medium-online" in models

    @pytest.mark.asyncio
    async def test_sonar_performance_benchmark(self, mock_openrouter_service, sample_sonar_query):
        """Test sonar performance benchmarks."""
        result = ResearchResult(
            query=sample_sonar_query.query,
            answer="Comprehensive reasoning analysis...",
            sources=["https://example.com"],
            confidence_score=0.95,
            processing_time=2.8,
            model_used="perplexity/sonar-reasoning-pro",
            token_usage={"total_tokens": 1500}
        )
        
        mock_openrouter_service.research.return_value = result
        
        research_result = await mock_openrouter_service.research(sample_sonar_query)
        
        # Performance expectations for sonar-reasoning-pro
        assert research_result.processing_time < 5.0  # Should be fast
        assert research_result.confidence_score >= 0.8  # High confidence
        assert research_result.token_usage["total_tokens"] < 2000  # Reasonable token usage


class TestOpenRouterIntegration:
    """Integration tests for OpenRouter with Perplexity."""

    @pytest.fixture
    def openrouter_config(self):
        """Create OpenRouter configuration."""
        return ResearchConfig(
            api_key="test-openrouter-key",
            base_url="https://openrouter.ai/api/v1",
            default_model="perplexity/sonar-reasoning-pro",
            max_tokens=4000,
            temperature=0.1
        )

    def test_openrouter_config_validation(self, openrouter_config):
        """Test OpenRouter configuration."""
        assert openrouter_config.api_key == "test-openrouter-key"
        assert openrouter_config.default_model == "perplexity/sonar-reasoning-pro"
        openrouter_config.validate()

    @pytest.mark.asyncio
    async def test_openrouter_service_initialization(self, openrouter_config):
        """Test OpenRouter service initialization."""
        service = OpenRouterResearchService(openrouter_config)
        
        assert hasattr(service, 'research')
        assert hasattr(service, 'get_available_models')
        assert callable(service.research)
        assert callable(service.get_available_models)


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
