import pytest
from unittest.mock import patch, AsyncMock, MagicMock, PropertyMock
import logging
import uuid

from app.api.lifecycle import project_stats


class TestLifecycleExceptionHandling:
    """测试 lifecycle.py 中的异常处理行为"""

    @pytest.mark.asyncio
    async def test_project_stats_handles_content_query_failure(self, caplog):
        """测试 project_stats 当 Content 查询失败时的处理"""
        from app.models.user import User

        org_id = uuid.uuid4()
        user_id = uuid.uuid4()

        user = User(
            id=user_id,
            email="test@example.com",
            password_hash="hash",
            name="Test User",
            plan="free",
            organization_id=org_id,
        )

        execute_results = [
            MagicMock(one=MagicMock(total=0, active=0)),
            MagicMock(),
            MagicMock(),
            MagicMock(),
            MagicMock(),
        ]
        execute_results[1].all.return_value = []
        execute_results[2].scalar.return_value = 0
        execute_results[3].all.return_value = []
        execute_results[4].all.return_value = []
        execute_count = [0]

        def execute_side_effect(*args, **kwargs):
            idx = execute_count[0]
            execute_count[0] += 1
            if idx == 2:
                raise RuntimeError("Content table not available")
            return execute_results[idx]

        mock_session = AsyncMock()
        mock_session.execute.side_effect = execute_side_effect

        with caplog.at_level(logging.WARNING):
            result = await project_stats(
                db=mock_session,
                current_user=user
            )

        assert result.contents_produced == 0
        assert any("Failed to count contents" in record.message for record in caplog.records)

    @pytest.mark.asyncio
    async def test_project_stats_handles_citation_query_failure(self, caplog):
        """测试 project_stats 当 CitationRecord 查询失败时的处理"""
        from app.models.user import User

        org_id = uuid.uuid4()
        user_id = uuid.uuid4()

        user = User(
            id=user_id,
            email="test@example.com",
            password_hash="hash",
            name="Test User",
            plan="free",
            organization_id=org_id,
        )

        execute_results = [
            MagicMock(one=MagicMock(total=0, active=0)),
            MagicMock(),
            MagicMock(),
            MagicMock(),
            MagicMock(),
            MagicMock(),
        ]
        execute_results[1].all.return_value = []
        execute_results[2].scalar.return_value = 0
        execute_results[3].all.return_value = []
        execute_results[4].one.return_value = MagicMock(total_citations=0, cited_count=0)
        execute_results[5].all.return_value = []
        execute_count = [0]

        def execute_side_effect(*args, **kwargs):
            idx = execute_count[0]
            execute_count[0] += 1
            if idx == 4:
                raise RuntimeError("CitationRecord table not available")
            return execute_results[idx]

        mock_session = AsyncMock()
        mock_session.execute.side_effect = execute_side_effect

        with caplog.at_level(logging.WARNING):
            result = await project_stats(
                db=mock_session,
                current_user=user
            )

        assert result.avg_ai_citation_rate is None
        assert any("Failed to calculate AI citation rate" in record.message for record in caplog.records)
