"""
錯誤處理框架測試模組

測試 ErrorHandler 類的各項功能，包括：
- 錯誤類型自動分類
- 用戶友好錯誤信息生成
- 國際化支持
- 錯誤上下文記錄
"""

import pytest
import sys
import os
from unittest.mock import patch, MagicMock

# 添加 src 目錄到 Python 路徑
sys.path.insert(0, 'src')

from mcp_feedback_enhanced.utils.error_handler import ErrorHandler, ErrorType, ErrorSeverity


class TestErrorHandler:
    """錯誤處理器測試類"""
    
    def test_classify_error_network(self):
        """測試網絡錯誤分類"""
        # 測試 ConnectionError
        error = ConnectionError("Connection failed")
        assert ErrorHandler.classify_error(error) == ErrorType.NETWORK

        # 測試包含網絡關鍵字的錯誤（不包含 timeout）
        error = Exception("socket connection failed")
        assert ErrorHandler.classify_error(error) == ErrorType.NETWORK
    
    def test_classify_error_file_io(self):
        """測試文件 I/O 錯誤分類"""
        # 測試 FileNotFoundError
        error = FileNotFoundError("No such file or directory")
        assert ErrorHandler.classify_error(error) == ErrorType.FILE_IO

        # 測試包含文件關鍵字的錯誤（不包含權限關鍵字）
        error = Exception("file not found")
        assert ErrorHandler.classify_error(error) == ErrorType.FILE_IO
    
    def test_classify_error_timeout(self):
        """測試超時錯誤分類"""
        error = TimeoutError("Operation timed out")
        assert ErrorHandler.classify_error(error) == ErrorType.TIMEOUT
        
        error = Exception("timeout occurred")
        assert ErrorHandler.classify_error(error) == ErrorType.TIMEOUT
    
    def test_classify_error_permission(self):
        """測試權限錯誤分類"""
        error = PermissionError("Access denied")
        assert ErrorHandler.classify_error(error) == ErrorType.PERMISSION
        
        error = Exception("access denied")
        assert ErrorHandler.classify_error(error) == ErrorType.PERMISSION
    
    def test_classify_error_validation(self):
        """測試驗證錯誤分類"""
        error = ValueError("Invalid value")
        assert ErrorHandler.classify_error(error) == ErrorType.VALIDATION
        
        error = TypeError("Wrong type")
        assert ErrorHandler.classify_error(error) == ErrorType.VALIDATION
    
    def test_classify_error_default_system(self):
        """測試默認系統錯誤分類"""
        error = Exception("Some completely unknown issue")
        assert ErrorHandler.classify_error(error) == ErrorType.SYSTEM
    
    def test_format_user_error_basic(self):
        """測試基本用戶友好錯誤信息生成"""
        error = ConnectionError("Connection failed")
        result = ErrorHandler.format_user_error(error)
        
        assert "❌" in result
        assert "網絡連接出現問題" in result or "网络连接出现问题" in result or "Network connection issue" in result
    
    def test_format_user_error_with_context(self):
        """測試帶上下文的錯誤信息生成"""
        error = FileNotFoundError("File not found")
        context = {
            "operation": "文件讀取",
            "file_path": "/path/to/file.txt"
        }
        
        result = ErrorHandler.format_user_error(error, context=context)
        
        assert "❌" in result
        assert "文件讀取" in result or "文件读取" in result or "文件讀取" in result
        assert "/path/to/file.txt" in result
    
    def test_format_user_error_with_technical_details(self):
        """測試包含技術細節的錯誤信息"""
        error = ValueError("Invalid input")
        result = ErrorHandler.format_user_error(error, include_technical=True)
        
        assert "❌" in result
        assert "ValueError" in result
        assert "Invalid input" in result
    
    def test_get_error_solutions(self):
        """測試獲取錯誤解決方案"""
        solutions = ErrorHandler.get_error_solutions(ErrorType.NETWORK)
        
        assert isinstance(solutions, list)
        assert len(solutions) > 0
        # 應該包含網絡相關的解決方案
        solutions_text = " ".join(solutions).lower()
        assert any(keyword in solutions_text for keyword in ["網絡", "网络", "network", "連接", "连接", "connection"])
    
    def test_log_error_with_context(self):
        """測試帶上下文的錯誤記錄"""
        error = Exception("Test error")
        context = {"operation": "測試操作", "user": "test_user"}
        
        error_id = ErrorHandler.log_error_with_context(error, context=context)
        
        assert isinstance(error_id, str)
        assert error_id.startswith("ERR_")
        assert len(error_id.split("_")) == 3  # ERR_timestamp_id
    
    def test_create_error_response(self):
        """測試創建標準化錯誤響應"""
        error = ConnectionError("Network error")
        context = {"operation": "網絡請求"}
        
        response = ErrorHandler.create_error_response(error, context=context)
        
        assert isinstance(response, dict)
        assert response["success"] is False
        assert "error_id" in response
        assert "error_type" in response
        assert "message" in response
        assert response["error_type"] == ErrorType.NETWORK.value
        assert "solutions" in response
    
    def test_create_error_response_for_user(self):
        """測試為用戶界面創建錯誤響應"""
        error = FileNotFoundError("File not found")
        
        response = ErrorHandler.create_error_response(error, for_user=True)
        
        assert response["success"] is False
        assert "context" not in response  # 用戶界面不應包含技術上下文
        assert "❌" in response["message"]  # 應該包含用戶友好的格式
    
    @patch('mcp_feedback_enhanced.utils.error_handler.ErrorHandler.get_i18n_error_message')
    def test_language_support(self, mock_get_message):
        """測試多語言支持"""
        error = ConnectionError("Network error")

        # 測試繁體中文
        mock_get_message.return_value = "網絡連接出現問題"
        result = ErrorHandler.format_user_error(error)
        assert "網絡連接出現問題" in result

        # 測試簡體中文
        mock_get_message.return_value = "网络连接出现问题"
        result = ErrorHandler.format_user_error(error)
        assert "网络连接出现问题" in result

        # 測試英文
        mock_get_message.return_value = "Network connection issue"
        result = ErrorHandler.format_user_error(error)
        assert "Network connection issue" in result
    
    def test_error_severity_logging(self):
        """測試錯誤嚴重程度記錄"""
        error = Exception("Critical system error")
        
        # 測試高嚴重程度錯誤
        error_id = ErrorHandler.log_error_with_context(
            error, 
            severity=ErrorSeverity.CRITICAL
        )
        
        assert isinstance(error_id, str)
        assert error_id.startswith("ERR_")
    
    def test_get_current_language_fallback(self):
        """測試語言獲取回退機制"""
        # 由於 i18n 系統可能會覆蓋環境變數，我們主要測試函數不會拋出異常
        language = ErrorHandler.get_current_language()
        assert isinstance(language, str)
        assert len(language) > 0

        # 測試語言代碼格式
        assert language in ["zh-TW", "zh-CN", "en"] or "-" in language
    
    def test_i18n_integration(self):
        """測試國際化系統集成"""
        # 測試當 i18n 系統不可用時的回退
        error_type = ErrorType.NETWORK
        
        # 測試獲取錯誤信息
        message = ErrorHandler.get_i18n_error_message(error_type)
        assert isinstance(message, str)
        assert len(message) > 0
        
        # 測試獲取解決方案
        solutions = ErrorHandler.get_i18n_error_solutions(error_type)
        assert isinstance(solutions, list)
    
    def test_error_context_preservation(self):
        """測試錯誤上下文保存"""
        error = Exception("Test error")
        context = {
            "operation": "測試操作",
            "file_path": "/test/path",
            "user_id": "test_user",
            "timestamp": "2025-01-05"
        }
        
        error_id = ErrorHandler.log_error_with_context(error, context=context)
        
        # 驗證錯誤 ID 格式
        assert isinstance(error_id, str)
        assert error_id.startswith("ERR_")
        
        # 上下文應該被記錄到調試日誌中（通過 debug_log）
        # 這裡我們主要驗證函數不會拋出異常
    
    def test_json_rpc_safety(self):
        """測試不影響 JSON RPC 通信"""
        # 錯誤處理應該只記錄到 stderr（通過 debug_log）
        # 不應該影響 stdout 或 JSON RPC 響應
        
        error = Exception("Test error for JSON RPC safety")
        context = {"operation": "JSON RPC 測試"}
        
        # 這些操作不應該影響 stdout
        error_id = ErrorHandler.log_error_with_context(error, context=context)
        user_message = ErrorHandler.format_user_error(error)
        response = ErrorHandler.create_error_response(error)
        
        # 驗證返回值類型正確
        assert isinstance(error_id, str)
        assert isinstance(user_message, str)
        assert isinstance(response, dict)
        
        # 驗證不會拋出異常
        assert error_id.startswith("ERR_")
        assert "❌" in user_message
        assert response["success"] is False


if __name__ == '__main__':
    # 運行測試
    pytest.main([__file__, '-v'])
