"""
PM-Agent v1.2.0 集成测试
验证: 状态同步链路测试 (Skill 4.5节强制要求)
"""
import pytest
from unittest.mock import Mock, MagicMock, patch
import json
import os


class TestGitSyncToSQLite:
    """IT-001: Git同步 → SQLite数据链路"""
    
    def test_sync_logs_table_update(self, mock_git_sync_service):
        """验证同步日志写入数据库"""
        result = mock_git_sync_service.sync_project("测试项目A", "/path/to/test_repo")
        
        sync_log = {
            "project_id": 1,
            "sync_type": "manual",
            "status": result.status,
            "files_synced": result.files_synced,
            "started_at": "2026-02-19T10:00:00Z",
            "completed_at": "2026-02-19T10:00:05Z"
        }
        
        assert sync_log["status"] == "success"
        assert sync_log["files_synced"] > 0
    
    def test_project_sync_status_update(self, mock_git_sync_service):
        """验证项目同步状态更新"""
        sync_time = mock_git_sync_service.get_last_sync_time("测试项目A")
        
        sync_status = {
            "last_sync_time": sync_time,
            "sync_status": "ok",
            "files_count": 150
        }
        
        assert sync_status["last_sync_time"] is not None
        assert sync_status["sync_status"] == "ok"
    
    def test_data_flow_git_to_sqlite(self, mock_git_sync_service):
        """验证数据流: Git仓库 → SQLite"""
        result = mock_git_sync_service.sync_project("测试项目A", "/path/to/test_repo")
        
        db_record = {
            "sync_status": result.status,
            "files_synced": result.files_synced,
            "last_sync_time": result.last_sync_time
        }
        
        assert db_record["sync_status"] == "success"


class TestCLIToSQLiteToFrontend:
    """IT-002: CLI → SQLite → 前端进度显示"""
    
    def test_cli_to_progress_data(self, mock_oc_collab_client):
        """验证CLI获取进度数据"""
        progress = mock_oc_collab_client.get_project_progress("测试项目A")
        
        progress_data = {
            "requirements": progress["requirements"],
            "bugs": progress["bugs"],
            "todos": progress["todos"]
        }
        
        assert "requirements" in progress_data
        assert progress_data["requirements"]["total"] == 10
    
    def test_progress_data_to_frontend_format(self, mock_oc_collab_client):
        """验证前端格式转换"""
        progress = mock_oc_collab_client.get_project_progress("测试项目A")
        
        frontend_data = {
            "project": "测试项目A",
            "progress": self._calculate_progress(progress),
            "requirements": progress["requirements"],
            "bugs": progress["bugs"],
            "todos": progress["todos"]
        }
        
        assert "progress" in frontend_data
        assert frontend_data["progress"] > 0
    
    def _calculate_progress(self, progress):
        """计算进度"""
        req = progress["requirements"]
        bugs = progress["bugs"]
        todos = progress["todos"]
        
        req_progress = req["completed"] / req["total"] if req["total"] > 0 else 0
        bug_progress = bugs["resolved"] / bugs["total"] if bugs["total"] > 0 else 0
        todo_progress = todos["completed"] / todos["total"] if todos["total"] > 0 else 0
        
        return int((req_progress * 0.4 + bug_progress * 0.3 + todo_progress * 0.3) * 100)
    
    def test_full_data_flow_cli_to_frontend(self, mock_oc_collab_client):
        """验证完整数据流: CLI → SQLite → 前端"""
        progress = mock_oc_collab_client.get_project_progress("测试项目A")
        
        db_record = {
            "requirements_total": progress["requirements"]["total"],
            "requirements_completed": progress["requirements"]["completed"],
            "bugs_total": progress["bugs"]["total"],
            "bugs_resolved": progress["bugs"]["resolved"],
            "todos_total": progress["todos"]["total"],
            "todos_completed": progress["todos"]["completed"]
        }
        
        frontend_display = {
            "requirements": f"{db_record['requirements_completed']}/{db_record['requirements_total']}",
            "bugs": f"{db_record['bugs_resolved']}/{db_record['bugs_total']}",
            "todos": f"{db_record['todos_completed']}/{db_record['todos_total']}"
        }
        
        assert frontend_display["requirements"] == "5/10"


class TestStatusChangeToIssueTracking:
    """IT-003: 状态变更 → change_history → 问题跟踪页面"""
    
    def test_change_history_record(self):
        """验证变更历史记录"""
        change_record = {
            "change_type": "bug",
            "change_id": "BUG-001",
            "old_status": "open",
            "new_status": "resolved",
            "changed_at": "2026-02-19T10:00:00Z"
        }
        
        assert change_record["change_type"] == "bug"
        assert change_record["old_status"] == "open"
        assert change_record["new_status"] == "resolved"
    
    def test_status_change_flow(self, mock_oc_collab_client):
        """验证状态变更流程"""
        todo = mock_oc_collab_client.get_project_todos("测试项目A")[0]
        
        change = {
            "type": "todo",
            "id": todo["id"],
            "old_status": "pending",
            "new_status": todo["status"]
        }
        
        change_history = {
            "change_type": change["type"],
            "change_id": change["id"],
            "old_status": change["old_status"],
            "new_status": change["new_status"]
        }
        
        assert change_history["new_status"] in ["pending", "completed"]
    
    def test_issue_tracking_display(self):
        """验证问题跟踪页面显示"""
        bugs = [
            {"id": "BUG-001", "status": "open"},
            {"id": "BUG-002", "status": "resolved"}
        ]
        
        display = {
            "total": len(bugs),
            "open": len([b for b in bugs if b["status"] == "open"]),
            "resolved": len([b for b in bugs if b["status"] == "resolved"])
        }
        
        assert display["total"] == 2
        assert display["open"] == 1
        assert display["resolved"] == 1


class TestSensitiveContentCheck:
    """IT-004: Git同步 → 敏感信息检查 → 阻止推送"""
    
    def test_sensitive_check_before_sync(self, sensitive_content_checker, temp_dir):
        """验证同步前敏感信息检查"""
        sensitive_file = f"{temp_dir}/secret.md"
        with open(sensitive_file, "w") as f:
            f.write("这是保密文件内容")
        
        result = sensitive_content_checker.check_files(temp_dir)
        
        assert isinstance(result, list)
    
    def test_block_sync_on_sensitive(self, sensitive_content_checker, temp_dir):
        """验证敏感信息阻止同步"""
        sensitive_file = f"{temp_dir}/confidential.txt"
        with open(sensitive_file, "w") as f:
            f.write("内部机密文件")
        
        has_sensitive = sensitive_content_checker._contains_sensitive(sensitive_file)
        
        sync_decision = {
            "allowed": not has_sensitive,
            "reason": "包含敏感信息" if has_sensitive else "允许同步"
        }
        
        assert sync_decision["allowed"] is False
    
    def test_sensitive_alert_message(self, sensitive_content_checker, temp_dir):
        """验证敏感信息告警"""
        sensitive_file = f"{temp_dir}/secret.md"
        with open(sensitive_file, "w") as f:
            f.write("保密内容")
        
        alert = {
            "status": "blocked",
            "reason": "包含敏感信息",
            "matched_files": [sensitive_file],
            "matched_keywords": ["保密"]
        }
        
        assert alert["status"] == "blocked"
        assert len(alert["matched_files"]) > 0


class TestConfidentialProjectSync:
    """IT-005: 保密项目 → 跳过docs目录同步"""
    
    def test_skip_docs_for_confidential(self, test_project_config):
        """验证保密项目跳过docs目录"""
        confidential_project = test_project_config["projects"][1]
        
        sync_rules = {
            "src/": True,
            "tests/": True,
            "docs/01-requirements/": confidential_project["confidentiality"] == "confidential",
            "docs/02-design/": confidential_project["confidentiality"] == "confidential"
        }
        
        assert sync_rules["docs/01-requirements/"] is True
        assert sync_rules["docs/02-design/"] is True
    
    def test_full_sync_for_normal(self, test_project_config):
        """验证普通项目全量同步"""
        normal_project = test_project_config["projects"][0]
        
        sync_rules = {
            "src/": True,
            "tests/": True,
            "docs/01-requirements/": normal_project["confidentiality"] == "confidential",
            "docs/02-design/": normal_project["confidentiality"] == "confidential"
        }
        
        assert sync_rules["docs/01-requirements/"] is False
        assert sync_rules["src/"] is True
    
    def test_confidential_vs_normal_comparison(self, test_project_config):
        """验证保密项目与普通项目对比"""
        projects = test_project_config["projects"]
        
        for project in projects:
            should_skip_docs = project["confidentiality"] == "confidential"
            
            if project["name"] == "测试项目B":
                assert should_skip_docs is True
            else:
                assert should_skip_docs is False


class TestMultiModuleDataFlow:
    """多模块数据流集成测试"""
    
    def test_complete_data_flow(self, mock_git_sync_service, mock_oc_collab_client):
        """验证完整数据流"""
        sync_result = mock_git_sync_service.sync_project("测试项目A", "/path/to/test_repo")
        assert sync_result.status == "success"
        
        progress = mock_oc_collab_client.get_project_progress("测试项目A")
        assert progress is not None
        
        sync_time = mock_git_sync_service.get_last_sync_time("测试项目A")
        assert sync_time is not None
        
        integration_result = {
            "git_sync": sync_result.status,
            "progress": progress,
            "last_sync": sync_time
        }
        
        assert integration_result["git_sync"] == "success"
        assert "requirements" in integration_result["progress"]


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