"""
PM-Agent v1.2.0 Final Push Coverage Tests

最后一轮测试，将所有v1.2.0服务覆盖率提升至80%以上
"""
import os
import sys
import pytest
import tempfile
import shutil
from pathlib import Path
from unittest.mock import Mock, patch, MagicMock
from datetime import datetime, timedelta

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


class TestGitSyncFinalPush:
    """GitSyncService 最后冲刺覆盖率"""

    @pytest.fixture
    def temp_dir(self):
        temp = tempfile.mkdtemp()
        yield temp
        shutil.rmtree(temp, ignore_errors=True)

    def test_sync_result_full(self):
        """测试完整同步结果"""
        from backend.services.git_sync_service import SyncResult
        
        result = SyncResult(
            success=True,
            project_name="test",
            started_at=datetime.now()
        )
        
        result.files_added = 5
        result.files_modified = 3
        result.files_deleted = 1
        result.files_synced = 9
        result.completed_at = datetime.now()
        
        assert result.success is True
        assert result.files_added == 5

    @patch('backend.services.git_sync_service.Repo')
    def test_clone_path_exists(self, mock_repo, temp_dir):
        """测试克隆路径已存在"""
        from backend.services.git_sync_service import GitSyncService
        
        project_path = os.path.join(temp_dir, "existing")
        os.makedirs(project_path)
        
        mock_repo.clone_from.return_value = Mock()
        
        service = GitSyncService(base_path=temp_dir)
        
        result = service._clone_repo(
            "https://github.com/test/repo.git",
            project_path,
            "existing",
            datetime.now()
        )
        
        assert result is not None


class TestProgressFinalPush:
    """ProgressService 最后冲刺覆盖率"""

    def test_requirements_progress_dataclass(self):
        """测试需求进度数据类"""
        from backend.services.progress_service import RequirementsProgress
        
        req = RequirementsProgress(
            total=10,
            completed=5,
            in_progress=3,
            pending=2
        )
        
        assert req.total == 10
        assert req.completed == 5

    def test_bugs_progress_dataclass(self):
        """测试BUG进度数据类"""
        from backend.services.progress_service import BugsProgress
        
        bugs = BugsProgress(
            total=5,
            resolved=3,
            open=2
        )
        
        assert bugs.total == 5

    def test_todos_progress_dataclass(self):
        """测试TODO进度数据类"""
        from backend.services.progress_service import TodosProgress
        
        todos = TodosProgress(
            total=20,
            completed=10,
            pending=10
        )
        
        assert todos.total == 20

    def test_project_progress_dataclass(self):
        """测试项目进度数据类"""
        from backend.services.progress_service import (
            ProjectProgress, RequirementsProgress, BugsProgress, TodosProgress
        )
        
        progress = ProjectProgress(
            project_name="test",
            overall_progress=75,
            requirements=RequirementsProgress(total=10, completed=5),
            bugs=BugsProgress(total=5, resolved=3),
            todos=TodosProgress(total=20, completed=10)
        )
        
        assert progress.project_name == "test"
        assert progress.overall_progress == 75

    def test_projects_summary_dataclass(self):
        """测试项目汇总数据类"""
        from backend.services.progress_service import ProjectsSummary
        
        summary = ProjectsSummary(
            total_projects=5,
            active_projects=3,
            avg_progress=50,
            projects=[]
        )
        
        assert summary.total_projects == 5


class TestIssueSyncFinalPush:
    """IssueSyncService 最后冲刺覆盖率"""

    def test_sync_bug_dataclass(self):
        """测试同步BUG数据类"""
        from backend.services.issue_sync_service import SyncBug
        
        bug = SyncBug(
            id="BUG-001",
            title="Test bug",
            status="resolved",
            severity="high",
            description="Test description",
            assignee="John",
            created_at=datetime.now(),
            resolved_at=datetime.now()
        )
        
        assert bug.id == "BUG-001"
        assert bug.severity == "high"

    def test_sync_requirement_dataclass(self):
        """测试同步需求数据类"""
        from backend.services.issue_sync_service import SyncRequirement
        
        req = SyncRequirement(
            id="REQ-001",
            title="Test requirement",
            status="implemented",
            priority="high",
            background="Background",
            user_scenario="As a user",
            expected_behavior="System should",
            estimated_hours=8.0,
            created_at=datetime.now(),
            implemented_at=datetime.now()
        )
        
        assert req.id == "REQ-001"


class TestStatusFeedbackFinalPush:
    """StatusFeedbackService 最后冲刺覆盖率"""

    def test_change_type_enum(self):
        """测试变更类型枚举"""
        from backend.services.status_feedback_service import ChangeType
        
        assert ChangeType.BUG.value == "bug"
        assert ChangeType.REQUIREMENT.value == "requirement"
        assert ChangeType.TODO.value == "todo"
        assert ChangeType.PROGRESS.value == "progress"

    def test_change_event_full(self):
        """测试完整变更事件"""
        from backend.services.status_feedback_service import ChangeEvent, ChangeType
        
        event = ChangeEvent(
            project_name="test",
            change_type=ChangeType.BUG,
            change_id="BUG-001",
            title="Test bug",
            old_status="open",
            new_status="closed",
            old_value="10",
            new_value="20",
            description="Fixed",
            changed_at=datetime.now(),
            source="oc_collab"
        )
        
        assert event.change_type == ChangeType.BUG
        assert event.old_value == "10"


class TestSyncPermissionFinalPush:
    """SyncPermissionService 最后冲刺覆盖率"""

    def test_sync_permission_dataclass(self):
        """测试同步权限数据类"""
        from backend.services.sync_permission_service import SyncPermission
        
        perm = SyncPermission(
            allowed=True,
            reason="Normal project",
            requires_confirmation=False,
            warnings=["Warning 1", "Warning 2"]
        )
        
        assert perm.allowed is True
        assert len(perm.warnings) == 2


class TestDocumentFetcherFinalPush:
    """DocumentFetcher 最后冲刺覆盖率"""

    def test_document_dataclass(self):
        """测试文档数据类"""
        from backend.services.document_fetcher import Document
        
        doc = Document(
            name="test.md",
            path="docs/test.md",
            category="文档",
            file_type="md",
            size=1024,
            content="test content",
            modified_at=datetime.now()
        )
        
        assert doc.name == "test.md"
        assert doc.size == 1024

    def test_document_category_dataclass(self):
        """测试文档分类数据类"""
        from backend.services.document_fetcher import DocumentCategory
        
        cat = DocumentCategory(
            name="文档",
            path="docs",
            document_count=10,
            subcategories=[]
        )
        
        assert cat.name == "文档"
        assert cat.document_count == 10


class TestConfidentialCheckerFinalPush:
    """ConfidentialChecker 最后冲刺覆盖率"""

    def test_sensitive_file_dataclass(self):
        """测试敏感文件数据类"""
        from backend.services.confidential_checker import SensitiveFile
        
        sf = SensitiveFile(
            path="/test/secret.txt",
            matched_keywords=["secret", "password"],
            line_numbers=[10, 20, 30],
            suggestion="Remove sensitive data"
        )
        
        assert len(sf.matched_keywords) == 2

    def test_sensitive_check_result_dataclass(self):
        """测试检查结果数据类"""
        from backend.services.confidential_checker import SensitiveCheckResult, SensitiveFile
        
        result = SensitiveCheckResult(
            has_sensitive=True,
            files_count=3,
            files=[
                SensitiveFile(path="1", matched_keywords=["k"], line_numbers=[1])
            ],
            warning_message="Found sensitive data",
            blocked=True
        )
        
        assert result.has_sensitive is True
        assert result.blocked is True


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