"""
SOVR SDK 客户端测试
"""

import pytest
from unittest.mock import Mock, patch
import json

from sovr_sdk import SOVRClient
from sovr_sdk.models import DecisionResult, TrustBundle, Evidence
from sovr_sdk.exceptions import (
    SOVRError,
    AuthenticationError,
    RateLimitError,
    ValidationError,
)


class TestSOVRClient:
    """SOVRClient 测试类"""
    
    @pytest.fixture
    def client(self):
        """创建测试客户端"""
        return SOVRClient(
            api_key="test-api-key",
            tenant_id="test-tenant",
            endpoint="https://api.test.sovr.ai"
        )
    
    def test_init_with_params(self):
        """测试使用参数初始化"""
        client = SOVRClient(
            api_key="key",
            tenant_id="tenant",
            endpoint="https://api.test.com"
        )
        assert client.api_key == "key"
        assert client.tenant_id == "tenant"
        assert client.endpoint == "https://api.test.com"
    
    def test_init_missing_api_key(self):
        """测试缺少 API Key 时抛出异常"""
        with pytest.raises(ValueError, match="api_key"):
            SOVRClient(tenant_id="tenant", endpoint="https://api.test.com")
    
    def test_init_missing_tenant_id(self):
        """测试缺少 Tenant ID 时抛出异常"""
        with pytest.raises(ValueError, match="tenant_id"):
            SOVRClient(api_key="key", endpoint="https://api.test.com")
    
    @patch("sovr_sdk.client.requests.Session.request")
    def test_evaluate_decision_approved(self, mock_request, client):
        """测试决策评估 - 批准"""
        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.text = json.dumps({
            "requestId": "req-001",
            "verdict": "approved",
            "riskScore": 15,
            "valueScore": 85,
            "processedAt": "2026-01-25T10:00:00Z"
        })
        mock_response.json.return_value = json.loads(mock_response.text)
        mock_request.return_value = mock_response
        
        result = client.evaluate_decision(
            action="payment",
            resource="order/123",
            context={"amount": 100}
        )
        
        assert isinstance(result, DecisionResult)
        assert result.verdict == "approved"
        assert result.is_approved
        assert not result.is_denied
        assert result.risk_score == 15
        assert result.value_score == 85
    
    @patch("sovr_sdk.client.requests.Session.request")
    def test_evaluate_decision_denied(self, mock_request, client):
        """测试决策评估 - 拒绝"""
        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.text = json.dumps({
            "requestId": "req-002",
            "verdict": "denied",
            "riskScore": 85,
            "valueScore": 15,
            "reason": "金额超过阈值",
            "processedAt": "2026-01-25T10:00:00Z"
        })
        mock_response.json.return_value = json.loads(mock_response.text)
        mock_request.return_value = mock_response
        
        result = client.evaluate_decision(
            action="payment",
            resource="order/456",
            context={"amount": 100000}
        )
        
        assert result.verdict == "denied"
        assert result.is_denied
        assert not result.is_approved
        assert result.reason == "金额超过阈值"
    
    @patch("sovr_sdk.client.requests.Session.request")
    def test_authentication_error(self, mock_request, client):
        """测试认证错误"""
        mock_response = Mock()
        mock_response.status_code = 401
        mock_request.return_value = mock_response
        
        with pytest.raises(AuthenticationError):
            client.evaluate_decision(action="test", resource="test")
    
    @patch("sovr_sdk.client.requests.Session.request")
    def test_rate_limit_error(self, mock_request, client):
        """测试频率限制错误"""
        mock_response = Mock()
        mock_response.status_code = 429
        mock_response.headers = {"Retry-After": "120"}
        mock_request.return_value = mock_response
        
        with pytest.raises(RateLimitError) as exc_info:
            client.evaluate_decision(action="test", resource="test")
        
        assert exc_info.value.retry_after == 120
    
    @patch("sovr_sdk.client.requests.Session.request")
    def test_create_trust_bundle(self, mock_request, client):
        """测试创建信任包"""
        mock_response = Mock()
        mock_response.status_code = 200
        mock_response.text = json.dumps({
            "id": 1,
            "name": "测试信任包",
            "status": "draft",
            "createdAt": "2026-01-25T10:00:00Z"
        })
        mock_response.json.return_value = json.loads(mock_response.text)
        mock_request.return_value = mock_response
        
        bundle = client.create_trust_bundle(
            name="测试信任包",
            description="测试描述"
        )
        
        assert isinstance(bundle, TrustBundle)
        assert bundle.id == 1
        assert bundle.name == "测试信任包"
        assert bundle.status == "draft"
    
    def test_verify_webhook_signature_valid(self):
        """测试 Webhook 签名验证 - 有效"""
        payload = b'{"event": "test"}'
        secret = "test-secret"
        
        import hmac
        import hashlib
        expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
        
        assert SOVRClient.verify_webhook_signature(
            payload=payload,
            signature=f"sha256={expected}",
            secret=secret
        )
    
    def test_verify_webhook_signature_invalid(self):
        """测试 Webhook 签名验证 - 无效"""
        payload = b'{"event": "test"}'
        
        assert not SOVRClient.verify_webhook_signature(
            payload=payload,
            signature="sha256=invalid",
            secret="test-secret"
        )


class TestDecisionResult:
    """DecisionResult 测试类"""
    
    def test_from_dict(self):
        """测试从字典创建"""
        data = {
            "requestId": "req-001",
            "verdict": "approved",
            "riskScore": 20,
            "valueScore": 80,
            "processedAt": "2026-01-25T10:00:00Z"
        }
        
        result = DecisionResult.from_dict(data)
        
        assert result.request_id == "req-001"
        assert result.verdict == "approved"
        assert result.risk_score == 20
        assert result.value_score == 80
    
    def test_is_approved(self):
        """测试 is_approved 属性"""
        result = DecisionResult.from_dict({
            "requestId": "1",
            "verdict": "approved",
            "riskScore": 0,
            "valueScore": 100,
            "processedAt": ""
        })
        
        assert result.is_approved
        assert not result.is_denied
        assert not result.needs_approval
    
    def test_needs_approval(self):
        """测试 needs_approval 属性"""
        result = DecisionResult.from_dict({
            "requestId": "1",
            "verdict": "pending_approval",
            "riskScore": 50,
            "valueScore": 50,
            "processedAt": ""
        })
        
        assert result.needs_approval
        assert not result.is_approved
        assert not result.is_denied


class TestTrustBundle:
    """TrustBundle 测试类"""
    
    def test_is_active(self):
        """测试 is_active 属性"""
        bundle = TrustBundle.from_dict({
            "id": 1,
            "name": "test",
            "status": "active",
            "createdAt": ""
        })
        
        assert bundle.is_active
    
    def test_is_sufficient(self):
        """测试 is_sufficient 属性"""
        bundle = TrustBundle.from_dict({
            "id": 1,
            "name": "test",
            "status": "active",
            "createdAt": "",
            "sufficiencyScore": 0.75
        })
        
        assert bundle.is_sufficient
        
        bundle.sufficiency_score = 0.5
        assert not bundle.is_sufficient
