"""
VersionClient 单元测试 - HTTP API版本
PM-Agent v2.0 - F-032

测试用例: 35个 (重写为HTTP API版本)
"""
import pytest
import sys
from pathlib import Path
from unittest.mock import Mock, patch, MagicMock

sys.path.insert(0, str(Path(__file__).parent.parent / "backend"))


@pytest.fixture(autouse=True)
def reset_client():
    """重置全局client"""
    from backend.integrations.version_api_client import set_version_api_client, VersionAPIClient
    mock_client = MagicMock()
    set_version_api_client(mock_client)
    yield
    set_version_api_client(None)


class TestVersionClientInit:
    """测试VersionClient初始化"""

    def test_init_with_default_timeout(self):
        """TC-001: 测试默认超时初始化"""
        from backend.services.version_service import VersionClient
        client = VersionClient()
        assert client.timeout == 30

    def test_init_with_custom_timeout(self):
        """TC-002: 测试自定义超时"""
        from backend.services.version_service import VersionClient
        client = VersionClient(timeout=60)
        assert client.timeout == 60


class TestVersionClientAPI:
    """测试VersionClient HTTP API调用"""

    def test_list_versions_empty(self):
        """TC-005: 测试版本列表为空"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.list_versions.return_value = []
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.list_versions()
        assert result == []

    def test_list_versions_with_data(self):
        """TC-006: 测试版本列表有数据"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.list_versions.return_value = [
            {"version": "v1.0.0", "status": "released"}
        ]
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.list_versions()
        assert len(result) == 1
        assert result[0]["version"] == "v1.0.0"

    def test_list_versions_filter_by_status(self):
        """TC-007: 测试按状态过滤"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.list_versions.return_value = [
            {"version": "v1.0.0", "status": "released"}
        ]
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.list_versions(status="released")
        mock_client.list_versions.assert_called_once_with(status="released", project=None)

    def test_show_version_success(self):
        """TC-008: 测试获取版本详情"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.show_version.return_value = {
            "version": "v1.0.0",
            "status": "released",
            "project": "pm-agent"
        }
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.show_version("v1.0.0")
        assert result["version"] == "v1.0.0"

    def test_register_version_success(self):
        """TC-009: 测试登记版本"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.register_version.return_value = {
            "version": "v1.0.0",
            "status": "draft"
        }
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.register_version("v1.0.0")
        assert result["version"] == "v1.0.0"

    def test_release_version_success(self):
        """TC-010: 测试发布版本"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.release_version.return_value = {
            "version": "v1.0.0",
            "status": "released"
        }
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.release_version("v1.0.0")
        assert result["status"] == "released"

    def test_rollback_version_success(self):
        """TC-011: 测试回滚版本"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.rollback_version.return_value = {
            "version": "v1.0.0",
            "status": "draft"
        }
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.rollback_version("v1.0.0")
        assert result["version"] == "v1.0.0"

    def test_get_dependencies_success(self):
        """TC-012: 测试获取依赖"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.get_dependencies.return_value = [
            {"name": "dep1", "version": "1.0.0"}
        ]
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.get_dependencies("v1.0.0")
        assert len(result) == 1

    def test_list_projects_success(self):
        """TC-013: 测试列出项目"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.list_projects.return_value = [
            {"name": "pm-agent", "version_count": 5}
        ]
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.list_projects()
        assert len(result) == 1


class TestVersionClientErrors:
    """测试VersionClient错误处理"""

    def test_cli_execution_error(self):
        """TC-014: 测试API执行错误"""
        from backend.integrations.version_api_client import VersionAPIClientError, set_version_api_client
        
        mock_client = MagicMock()
        mock_client.list_versions.side_effect = VersionAPIClientError("Connection failed")
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        
        with pytest.raises(VersionAPIClientError):
            client.list_versions()

    def test_invalid_json_response(self):
        """TC-015: 测试无效JSON响应"""
        from backend.integrations.version_api_client import VersionAPIClientError, set_version_api_client
        
        mock_client = MagicMock()
        mock_client.list_versions.side_effect = VersionAPIClientError("Invalid JSON")
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        
        with pytest.raises(VersionAPIClientError):
            client.list_versions()

    def test_timeout_handling(self):
        """TC-016: 测试超时处理"""
        from backend.integrations.version_api_client import VersionAPIClientError, set_version_api_client
        
        mock_client = MagicMock()
        mock_client.list_versions.side_effect = VersionAPIClientError("Request timed out")
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient(timeout=5)
        
        with pytest.raises(VersionAPIClientError):
            client.list_versions()


class TestVersionClientEdgeCases:
    """测试VersionClient边界条件"""

    def test_empty_version_string(self):
        """TC-017: 测试空版本字符串"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.show_version.side_effect = ValueError("Version cannot be empty")
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        
        with pytest.raises(ValueError):
            client.show_version("")

    def test_special_chars_in_version(self):
        """TC-018: 测试版本号特殊字符"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.show_version.return_value = {"version": "v1.0.0"}
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.show_version("v1.0.0; DROP TABLE versions--")
        assert result is not None


class TestVersionClientCurrentVersion:
    """测试当前版本获取"""

    def test_get_current_version_success(self):
        """TC-019: 测试获取当前版本"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.get_current_version.return_value = "2.0.2"
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.get_current_version()
        assert result == "2.0.2"


class TestVersionClientRegisterV2:
    """测试版本登记V2"""

    def test_register_version_with_manifest(self):
        """TC-020: 测试带清单文件登记版本"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.register_version.return_value = {
            "version": "v1.0.0",
            "manifest": "loaded"
        }
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.register_version(
            "v1.0.0",
            manifest_path="/path/to/manifest.yaml"
        )
        assert result["manifest"] == "loaded"

    def test_register_version_with_test_report(self):
        """TC-021: 测试带测试报告登记版本"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.register_version.return_value = {
            "version": "v1.0.0",
            "test_report": "loaded"
        }
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.register_version(
            "v1.0.0",
            test_report_path="/path/to/report.json"
        )
        assert result["test_report"] == "loaded"


class TestVersionClientReleaseV2:
    """测试版本发布V2"""

    def test_release_version_not_found(self):
        """TC-022: 测试发布不存在的版本"""
        from backend.integrations.version_api_client import VersionAPIClientError, set_version_api_client
        
        mock_client = MagicMock()
        mock_client.release_version.side_effect = VersionAPIClientError("Version not found")
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        
        with pytest.raises(VersionAPIClientError):
            client.release_version("v99.99.99")


class TestVersionClientRollbackV2:
    """测试版本回滚V2"""

    def test_rollback_version_success(self):
        """TC-023: 测试回滚版本成功"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.rollback_version.return_value = {
            "version": "v1.0.0",
            "status": "draft",
            "previous_status": "released"
        }
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.rollback_version("v1.0.0")
        assert result["previous_status"] == "released"


class TestVersionClientProjectsV2:
    """测试项目V2"""

    def test_list_projects_empty(self):
        """TC-024: 测试项目列表为空"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.list_projects.return_value = []
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.list_projects()
        assert result == []

    def test_list_projects_with_data(self):
        """TC-025: 测试项目列表有数据"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.list_projects.return_value = [
            {"name": "pm-agent", "versions": 3},
            {"name": "test-agent", "versions": 2}
        ]
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.list_projects()
        assert len(result) == 2

    def test_show_project_success(self):
        """TC-026: 测试显示项目详情"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.show_project.return_value = {
            "name": "pm-agent",
            "versions": ["v1.0.0", "v2.0.0"]
        }
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.show_project("pm-agent")
        assert result["name"] == "pm-agent"


class TestVersionClientManifestV2:
    """测试清单V2"""

    def test_export_manifest_success(self):
        """TC-027: 测试导出清单"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.export_manifest.return_value = {"name": "pm-agent"}
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.export_manifest("v1.0.0", "/tmp/manifest.yaml")
        assert "name" in result

    def test_import_manifest_success(self):
        """TC-028: 测试导入清单"""
        from backend.integrations.version_api_client import set_version_api_client
        mock_client = MagicMock()
        mock_client.import_manifest.return_value = {"status": "success"}
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        result = client.import_manifest("/tmp/manifest.yaml")
        assert result["status"] == "success"


class TestVersionClientEdgeCasesV2:
    """测试边界条件V2"""

    def test_command_timeout(self):
        """TC-032: 测试请求超时"""
        from backend.integrations.version_api_client import VersionAPIClientError, set_version_api_client
        
        mock_client = MagicMock()
        mock_client.list_versions.side_effect = VersionAPIClientError("Request timed out")
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient(timeout=1)
        
        with pytest.raises(VersionAPIClientError):
            client.list_versions()

    def test_invalid_json_response(self):
        """TC-033: 测试无效JSON响应"""
        from backend.integrations.version_api_client import VersionAPIClientError, set_version_api_client
        
        mock_client = MagicMock()
        mock_client.list_versions.side_effect = VersionAPIClientError("Invalid JSON response")
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        
        with pytest.raises(VersionAPIClientError):
            client.list_versions()

    def test_api_not_available_error(self):
        """TC-034: 测试API不可用错误"""
        from backend.integrations.version_api_client import VersionAPIClientError, set_version_api_client
        
        mock_client = MagicMock()
        mock_client.list_versions.side_effect = VersionAPIClientError("Cannot connect to conf-man API")
        set_version_api_client(mock_client)
        
        from backend.services.version_service import VersionClient
        client = VersionClient()
        
        with pytest.raises(VersionAPIClientError) as exc_info:
            client.list_versions()
        
        assert "conf-man" in str(exc_info.value).lower()


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