"""Test LLM integration with reasoning-field fallback."""

import pytest
from unittest.mock import patch, MagicMock
from integrations.llm import call_llm


def test_reasoning_field_fallback():
    """Test that empty content field falls back to reasoning field."""
    
    def mock_api_response_with_reasoning(*args, **kwargs):
        class MockResponse:
            status_code = 200
            def json(self):
                return {
                    "choices": [{
                        "message": {
                            "content": "",
                            "reasoning": "This is from the reasoning field - GLM-5.1 style response.",
                        },
                        "finish_reason": "stop",
                    }],
                    "usage": {"total_tokens": 100},
                }
            def raise_for_status(self):
                pass
        
        return MockResponse()
    
    with patch('requests.post', side_effect=mock_api_response_with_reasoning):
        with patch('integrations.llm._get_api_config', return_value={"api_key": "test-key", "api_base": "https://test.api", "model": "test-model"}):
            content, metadata = call_llm("Test prompt")
    
    assert "reasoning field" in content
    assert "GLM-5.1" in content


def test_empty_response_raises_error():
    """Test that truly empty response (both fields) raises ValueError."""
    
    def mock_api_empty_response(*args, **kwargs):
        class MockResponse:
            status_code = 200
            def json(self):
                return {
                    "choices": [{
                        "message": {
                            "content": "",
                            "reasoning": "",
                        },
                        "finish_reason": "stop",
                    }],
                    "usage": {"total_tokens": 0},
                }
            def raise_for_status(self):
                pass
        
        return MockResponse()
    
    with patch('requests.post', side_effect=mock_api_empty_response):
        with patch('integrations.llm._get_api_config', return_value={"api_key": "test-key", "api_base": "https://test.api", "model": "test-model"}):
            with pytest.raises(ValueError) as excinfo:
                call_llm("Test prompt")
            
            assert "empty response" in str(excinfo.value).lower()


def test_normal_content_used_when_present():
    """Test that normal content field is preferred over reasoning."""
    
    def mock_api_normal_response(*args, **kwargs):
        class MockResponse:
            status_code = 200
            def json(self):
                return {
                    "choices": [{
                        "message": {
                            "content": "This is normal content.",
                            "reasoning": "This is reasoning that should be ignored.",
                        },
                        "finish_reason": "stop",
                    }],
                    "usage": {"total_tokens": 100},
                }
            def raise_for_status(self):
                pass
        
        return MockResponse()
    
    with patch('requests.post', side_effect=mock_api_normal_response):
        with patch('integrations.llm._get_api_config', return_value={"api_key": "test-key", "api_base": "https://test.api", "model": "test-model"}):
            content, metadata = call_llm("Test prompt")
    
    assert "normal content" in content
    assert "reasoning that should be ignored" not in content


def test_whitespace_only_content_triggers_fallback():
    """Test that whitespace-only content triggers reasoning fallback."""
    
    def mock_api_whitespace_response(*args, **kwargs):
        class MockResponse:
            status_code = 200
            def json(self):
                return {
                    "choices": [{
                        "message": {
                            "content": "   \n\t  ",
                            "reasoning": "Content was whitespace, using reasoning.",
                        },
                        "finish_reason": "stop",
                    }],
                    "usage": {"total_tokens": 50},
                }
            def raise_for_status(self):
                pass
        
        return MockResponse()
    
    with patch('requests.post', side_effect=mock_api_whitespace_response):
        with patch('integrations.llm._get_api_config', return_value={"api_key": "test-key", "api_base": "https://test.api", "model": "test-model"}):
            content, metadata = call_llm("Test prompt")
    
    assert "reasoning" in content


def test_metadata_includes_model_used():
    """Test that metadata includes model_used field."""
    
    def mock_api_response(*args, **kwargs):
        class MockResponse:
            status_code = 200
            def json(self):
                return {
                    "choices": [{
                        "message": {"content": "Test content", "reasoning": ""},
                        "finish_reason": "stop",
                    }],
                    "usage": {"total_tokens": 100},
                }
            def raise_for_status(self):
                pass
        
        return MockResponse()
    
    with patch('requests.post', side_effect=mock_api_response):
        with patch('integrations.llm._get_api_config', return_value={"api_key": "test-key", "api_base": "https://test.api", "model": "test-model"}):
            content, metadata = call_llm("Test prompt")
    
    assert "model_used" in metadata
    assert metadata["model_used"] == "test-model"