"""
Tests for log retrieval functionality
"""

import pytest
import json
from unittest.mock import patch, AsyncMock, MagicMock
from datadog_mcp.tools import get_logs
from datadog_mcp.utils import datadog_client
from mcp.types import CallToolResult, TextContent


class TestLogToolDefinition:
    """Test the get_logs tool definition"""
    
    def test_get_logs_tool_definition(self):
        """Test that get_logs tool definition is properly structured"""
        tool_def = get_logs.get_tool_definition()
        
        assert tool_def.name == "get_logs"
        assert "logs" in tool_def.description.lower()
        assert hasattr(tool_def, 'inputSchema')
        
        # Check required schema properties
        schema = tool_def.inputSchema
        assert "properties" in schema
        
        # Should have common parameters
        properties = schema["properties"]
        expected_params = ["query", "filters", "time_range", "limit", "format"]
        for param in expected_params:
            assert param in properties, f"Parameter {param} missing from schema"


class TestLogRetrieval:
    """Test log retrieval functionality"""
    
    @pytest.mark.asyncio
    async def test_fetch_logs_basic(self):
        """Test basic log fetching functionality"""
        # Mock the HTTP response
        mock_response_data = {
            "data": [
                {
                    "attributes": {
                        "timestamp": "2023-01-01T12:00:00Z",
                        "message": "Test log message",
                        "service": "test-service",
                        "status": "info"
                    }
                }
            ],
            "meta": {
                "page": {
                    "after": "next_cursor"
                }
            }
        }
        
        with patch('datadog_mcp.utils.datadog_client.httpx.AsyncClient') as mock_client:
            mock_client.return_value.__aenter__.return_value.post.return_value.json.return_value = mock_response_data
            mock_client.return_value.__aenter__.return_value.post.return_value.raise_for_status.return_value = None
            
            result = await datadog_client.fetch_logs()
            
            assert isinstance(result, list)
            assert len(result) > 0
            assert "message" in result[0]
    
    @pytest.mark.asyncio 
    async def test_fetch_logs_with_filters(self):
        """Test log fetching with filters"""
        filters = {
            "service": "web-app",
            "env": "production",
            "status": "error"
        }
        
        mock_response_data = {
            "data": [
                {
                    "attributes": {
                        "timestamp": "2023-01-01T12:00:00Z",
                        "message": "Error occurred",
                        "service": "web-app",
                        "status": "error"
                    }
                }
            ]
        }
        
        with patch('datadog_mcp.utils.datadog_client.httpx.AsyncClient') as mock_client:
            mock_client.return_value.__aenter__.return_value.post.return_value.json.return_value = mock_response_data
            mock_client.return_value.__aenter__.return_value.post.return_value.raise_for_status.return_value = None
            
            result = await datadog_client.fetch_logs(filters=filters)
            
            assert isinstance(result, list)
            # Verify filter was applied (would be in the request payload)
            mock_client.return_value.__aenter__.return_value.post.assert_called_once()


class TestLogToolHandler:
    """Test the get_logs tool handler"""
    
    @pytest.mark.asyncio
    async def test_handle_logs_request_success(self):
        """Test successful log request handling"""
        # Mock request
        mock_request = MagicMock()
        mock_request.arguments = {
            "query": "error",
            "time_range": "1h",
            "limit": 100,
            "format": "table"
        }
        
        # Mock log data
        mock_logs = [
            {
                "timestamp": "2023-01-01T12:00:00Z",
                "message": "Error in application",
                "service": "web-app",
                "status": "error"
            }
        ]
        
        with patch('datadog_mcp.utils.datadog_client.fetch_logs', new_callable=AsyncMock) as mock_fetch:
            mock_fetch.return_value = mock_logs
            
            result = await get_logs.handle_call(mock_request)
            
            assert isinstance(result, CallToolResult)
            assert result.isError is False
            assert len(result.content) > 0
            assert isinstance(result.content[0], TextContent)
            
            # Should contain log information
            content_text = result.content[0].text
            assert "Error in application" in content_text or "error" in content_text.lower()
    
    @pytest.mark.asyncio
    async def test_handle_logs_request_with_json_format(self):
        """Test log request with JSON format"""
        mock_request = MagicMock()
        mock_request.arguments = {
            "query": "info",
            "format": "json",
            "limit": 50
        }
        
        mock_logs = [
            {
                "timestamp": "2023-01-01T12:00:00Z",
                "message": "Info message",
                "service": "api",
                "status": "info"
            }
        ]
        
        with patch('datadog_mcp.utils.datadog_client.fetch_logs', new_callable=AsyncMock) as mock_fetch:
            mock_fetch.return_value = mock_logs
            
            result = await get_logs.handle_call(mock_request)
            
            assert isinstance(result, CallToolResult)
            assert result.isError is False
            
            content_text = result.content[0].text
            # Should be valid JSON when format is json
            if mock_request.arguments.get("format") == "json":
                try:
                    json.loads(content_text)
                except json.JSONDecodeError:
                    pytest.fail("Response should be valid JSON when format=json")
    
    @pytest.mark.asyncio
    async def test_handle_logs_request_error(self):
        """Test error handling in log requests"""
        mock_request = MagicMock()
        mock_request.arguments = {
            "query": "test",
            "time_range": "1h"
        }
        
        with patch('datadog_mcp.utils.datadog_client.fetch_logs', new_callable=AsyncMock) as mock_fetch:
            mock_fetch.side_effect = Exception("API error")
            
            result = await get_logs.handle_call(mock_request)
            
            assert isinstance(result, CallToolResult)
            assert result.isError is True
            assert len(result.content) > 0
            assert "error" in result.content[0].text.lower()
    
    @pytest.mark.asyncio
    async def test_handle_logs_request_empty_results(self):
        """Test handling when no logs are found"""
        mock_request = MagicMock()
        mock_request.arguments = {
            "query": "nonexistent",
            "time_range": "1h"
        }
        
        with patch('datadog_mcp.utils.datadog_client.fetch_logs', new_callable=AsyncMock) as mock_fetch:
            mock_fetch.return_value = []
            
            result = await get_logs.handle_call(mock_request)
            
            assert isinstance(result, CallToolResult)
            assert result.isError is False
            assert len(result.content) > 0
            
            content_text = result.content[0].text
            assert "no logs" in content_text.lower() or "no results" in content_text.lower()


class TestLogFormatting:
    """Test log data formatting"""
    
    def test_log_table_formatting(self):
        """Test that logs can be formatted as table"""
        sample_logs = [
            {
                "timestamp": "2023-01-01T12:00:00Z",
                "message": "Test message 1",
                "service": "service1",
                "status": "info"
            },
            {
                "timestamp": "2023-01-01T12:01:00Z", 
                "message": "Test message 2",
                "service": "service2",
                "status": "error"
            }
        ]
        
        # Import formatter and test
        from datadog_mcp.utils.formatters import format_logs_as_table
        
        try:
            table_output = format_logs_as_table(sample_logs)
            assert isinstance(table_output, str)
            assert len(table_output) > 0
            assert "service1" in table_output
            assert "service2" in table_output
        except ImportError:
            # If formatter doesn't exist, create a simple test
            assert len(sample_logs) == 2
    
    def test_log_json_formatting(self):
        """Test that logs can be formatted as JSON"""
        sample_logs = [
            {
                "timestamp": "2023-01-01T12:00:00Z",
                "message": "Test message",
                "service": "service1"
            }
        ]
        
        json_output = json.dumps(sample_logs, indent=2)
        assert isinstance(json_output, str)
        
        # Should be valid JSON
        parsed = json.loads(json_output)
        assert len(parsed) == 1
        assert parsed[0]["service"] == "service1"


class TestLogFiltering:
    """Test log filtering functionality"""
    
    @pytest.mark.asyncio
    async def test_logs_with_service_filter(self):
        """Test filtering logs by service"""
        filters = {"service": "web-api"}
        
        with patch('datadog_mcp.utils.datadog_client.httpx.AsyncClient') as mock_client:
            mock_response = {
                "data": [
                    {
                        "attributes": {
                            "message": "API request",
                            "service": "web-api"
                        }
                    }
                ]
            }
            mock_client.return_value.__aenter__.return_value.post.return_value.json.return_value = mock_response
            mock_client.return_value.__aenter__.return_value.post.return_value.raise_for_status.return_value = None
            
            result = await datadog_client.fetch_logs(filters=filters)
            
            # Verify the request was made with proper filters
            call_args = mock_client.return_value.__aenter__.return_value.post.call_args
            assert call_args is not None
    
    @pytest.mark.asyncio
    async def test_logs_with_time_range(self):
        """Test filtering logs by time range"""
        time_range = "4h"
        
        with patch('datadog_mcp.utils.datadog_client.httpx.AsyncClient') as mock_client:
            mock_response = {"data": []}
            mock_client.return_value.__aenter__.return_value.post.return_value.json.return_value = mock_response
            mock_client.return_value.__aenter__.return_value.post.return_value.raise_for_status.return_value = None
            
            result = await datadog_client.fetch_logs(time_range=time_range)
            
            # Verify the request was made
            mock_client.return_value.__aenter__.return_value.post.assert_called_once()


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