import unittest
from unittest.mock import patch, Mock, MagicMock
import json
import tempfile
import os

from pygeai.migration.comparison import (
    ResourceDiff,
    ProjectDiff,
    ProjectComparator,
    DiffFormatter
)


class TestResourceDiff(unittest.TestCase):
    def test_create_resource_diff(self):
        diff = ResourceDiff(
            resource_type="agents",
            only_in_source=[{"id": "1", "name": "Agent 1"}],
            only_in_destination=[{"id": "2", "name": "Agent 2"}],
            in_both=[{"id": "3", "name": "Agent 3"}],
            total_source=2,
            total_destination=2
        )
        
        self.assertEqual(diff.resource_type, "agents")
        self.assertEqual(len(diff.only_in_source), 1)
        self.assertEqual(len(diff.only_in_destination), 1)
        self.assertEqual(len(diff.in_both), 1)
        self.assertEqual(diff.total_source, 2)
        self.assertEqual(diff.total_destination, 2)

    def test_resource_diff_counts(self):
        diff = ResourceDiff(
            resource_type="tools",
            only_in_source=[{"id": "1"}, {"id": "2"}],
            only_in_destination=[],
            in_both=[{"id": "3"}],
            total_source=3,
            total_destination=1
        )
        
        self.assertEqual(len(diff.only_in_source), 2)
        self.assertEqual(len(diff.only_in_destination), 0)
        self.assertEqual(len(diff.in_both), 1)


class TestProjectDiff(unittest.TestCase):
    def test_create_project_diff(self):
        diff = ProjectDiff(
            source_project_id="proj-1",
            destination_project_id="proj-2",
            source_instance="https://api.test.ai",
            destination_instance="https://api.prod.ai",
            timestamp="2026-02-02T00:00:00"
        )
        
        self.assertEqual(diff.source_project_id, "proj-1")
        self.assertEqual(diff.destination_project_id, "proj-2")
        self.assertEqual(diff.source_instance, "https://api.test.ai")
        self.assertEqual(diff.destination_instance, "https://api.prod.ai")

    def test_project_diff_summary(self):
        diff = ProjectDiff(
            source_project_id="proj-1",
            destination_project_id="proj-2",
            source_instance="https://api.test.ai",
            destination_instance="https://api.prod.ai",
            summary={"resource_types_compared": 5, "total_differences": 10}
        )
        
        self.assertEqual(diff.summary["resource_types_compared"], 5)
        self.assertEqual(diff.summary["total_differences"], 10)


class TestProjectComparator(unittest.TestCase):
    @patch('pygeai.migration.comparison.AILabManager')
    def test_compare_agents_only_in_source(self, mock_lab_manager):
        mock_source_manager = Mock()
        mock_dest_manager = Mock()
        
        mock_source_agent = Mock()
        mock_source_agent.id = "agent-1"
        mock_source_agent.name = "Source Agent"
        
        mock_source_list = Mock()
        mock_source_list.agents = [mock_source_agent]
        mock_source_manager.list_agents.return_value = mock_source_list
        
        mock_dest_list = Mock()
        mock_dest_list.agents = []
        mock_dest_manager.list_agents.return_value = mock_dest_list
        
        mock_lab_manager.side_effect = [mock_source_manager, mock_dest_manager]
        
        comparator = ProjectComparator(
            from_api_key="src_key",
            from_instance="https://api.test.ai",
            from_project_id="proj-1",
            from_organization_id="org-1",
            to_api_key="dest_key",
            to_instance="https://api.prod.ai",
            to_project_id="proj-2",
            to_organization_id="org-2",
            resource_types=["agents"]
        )
        
        diff = comparator.compare()
        
        self.assertIn("agents", diff.resource_diffs)
        agent_diff = diff.resource_diffs["agents"]
        self.assertEqual(len(agent_diff.only_in_source), 1)
        self.assertEqual(len(agent_diff.only_in_destination), 0)
        self.assertEqual(agent_diff.only_in_source[0]["id"], "agent-1")

    @patch('pygeai.migration.comparison.AILabManager')
    def test_compare_agents_only_in_destination(self, mock_lab_manager):
        mock_source_manager = Mock()
        mock_dest_manager = Mock()
        
        mock_source_list = Mock()
        mock_source_list.agents = []
        mock_source_manager.list_agents.return_value = mock_source_list
        
        mock_dest_agent = Mock()
        mock_dest_agent.id = "agent-2"
        mock_dest_agent.name = "Dest Agent"
        
        mock_dest_list = Mock()
        mock_dest_list.agents = [mock_dest_agent]
        mock_dest_manager.list_agents.return_value = mock_dest_list
        
        mock_lab_manager.side_effect = [mock_source_manager, mock_dest_manager]
        
        comparator = ProjectComparator(
            from_api_key="src_key",
            from_instance="https://api.test.ai",
            from_project_id="proj-1",
            from_organization_id="org-1",
            to_api_key="dest_key",
            to_instance="https://api.prod.ai",
            to_project_id="proj-2",
            to_organization_id="org-2",
            resource_types=["agents"]
        )
        
        diff = comparator.compare()
        
        agent_diff = diff.resource_diffs["agents"]
        self.assertEqual(len(agent_diff.only_in_source), 0)
        self.assertEqual(len(agent_diff.only_in_destination), 1)
        self.assertEqual(agent_diff.only_in_destination[0]["id"], "agent-2")

    @patch('pygeai.migration.comparison.AILabManager')
    def test_compare_agents_in_both(self, mock_lab_manager):
        mock_source_manager = Mock()
        mock_dest_manager = Mock()
        
        mock_agent = Mock()
        mock_agent.id = "agent-shared"
        mock_agent.name = "Shared Agent"
        
        mock_source_list = Mock()
        mock_source_list.agents = [mock_agent]
        mock_source_manager.list_agents.return_value = mock_source_list
        
        mock_dest_list = Mock()
        mock_dest_list.agents = [mock_agent]
        mock_dest_manager.list_agents.return_value = mock_dest_list
        
        mock_lab_manager.side_effect = [mock_source_manager, mock_dest_manager]
        
        comparator = ProjectComparator(
            from_api_key="src_key",
            from_instance="https://api.test.ai",
            from_project_id="proj-1",
            from_organization_id="org-1",
            to_api_key="dest_key",
            to_instance="https://api.prod.ai",
            to_project_id="proj-2",
            to_organization_id="org-2",
            resource_types=["agents"]
        )
        
        diff = comparator.compare()
        
        agent_diff = diff.resource_diffs["agents"]
        self.assertEqual(len(agent_diff.only_in_source), 0)
        self.assertEqual(len(agent_diff.only_in_destination), 0)
        self.assertEqual(len(agent_diff.in_both), 1)
        self.assertEqual(agent_diff.in_both[0]["id"], "agent-shared")

    @patch('pygeai.migration.comparison.AILabManager')
    def test_compare_tools(self, mock_lab_manager):
        mock_source_manager = Mock()
        mock_dest_manager = Mock()
        
        mock_source_tool = Mock()
        mock_source_tool.id = "tool-1"
        mock_source_tool.name = "Tool 1"
        
        mock_source_list = Mock()
        mock_source_list.tools = [mock_source_tool]
        mock_source_manager.list_tools.return_value = mock_source_list
        
        mock_dest_list = Mock()
        mock_dest_list.tools = []
        mock_dest_manager.list_tools.return_value = mock_dest_list
        
        mock_lab_manager.side_effect = [mock_source_manager, mock_dest_manager]
        
        comparator = ProjectComparator(
            from_api_key="src_key",
            from_instance="https://api.test.ai",
            from_project_id="proj-1",
            from_organization_id="org-1",
            to_api_key="dest_key",
            to_instance="https://api.prod.ai",
            to_project_id="proj-2",
            to_organization_id="org-2",
            resource_types=["tools"]
        )
        
        diff = comparator.compare()
        
        self.assertIn("tools", diff.resource_diffs)
        tool_diff = diff.resource_diffs["tools"]
        self.assertEqual(len(tool_diff.only_in_source), 1)

    @patch('pygeai.migration.comparison.AILabManager')
    def test_compare_processes(self, mock_lab_manager):
        mock_source_manager = Mock()
        mock_dest_manager = Mock()
        
        mock_source_process = Mock()
        mock_source_process.id = "process-1"
        mock_source_process.name = "Process 1"
        
        mock_source_list = Mock()
        mock_source_list.processes = [mock_source_process]
        mock_source_manager.list_processes.return_value = mock_source_list
        
        mock_dest_list = Mock()
        mock_dest_list.processes = []
        mock_dest_manager.list_processes.return_value = mock_dest_list
        
        mock_lab_manager.side_effect = [mock_source_manager, mock_dest_manager]
        
        comparator = ProjectComparator(
            from_api_key="src_key",
            from_instance="https://api.test.ai",
            from_project_id="proj-1",
            from_organization_id="org-1",
            to_api_key="dest_key",
            to_instance="https://api.prod.ai",
            to_project_id="proj-2",
            to_organization_id="org-2",
            resource_types=["processes"]
        )
        
        diff = comparator.compare()
        
        self.assertIn("processes", diff.resource_diffs)
        process_diff = diff.resource_diffs["processes"]
        self.assertEqual(len(process_diff.only_in_source), 1)

    @patch('pygeai.migration.comparison.AILabManager')
    def test_compare_tasks(self, mock_lab_manager):
        mock_source_manager = Mock()
        mock_dest_manager = Mock()
        
        mock_source_task = Mock()
        mock_source_task.id = "task-1"
        mock_source_task.name = "Task 1"
        
        mock_source_list = Mock()
        mock_source_list.tasks = [mock_source_task]
        mock_source_manager.list_tasks.return_value = mock_source_list
        
        mock_dest_list = Mock()
        mock_dest_list.tasks = []
        mock_dest_manager.list_tasks.return_value = mock_dest_list
        
        mock_lab_manager.side_effect = [mock_source_manager, mock_dest_manager]
        
        comparator = ProjectComparator(
            from_api_key="src_key",
            from_instance="https://api.test.ai",
            from_project_id="proj-1",
            from_organization_id="org-1",
            to_api_key="dest_key",
            to_instance="https://api.prod.ai",
            to_project_id="proj-2",
            to_organization_id="org-2",
            resource_types=["tasks"]
        )
        
        diff = comparator.compare()
        
        self.assertIn("tasks", diff.resource_diffs)
        task_diff = diff.resource_diffs["tasks"]
        self.assertEqual(len(task_diff.only_in_source), 1)

    @patch('pygeai.migration.comparison.AILabManager')
    def test_compare_artifact_types(self, mock_lab_manager):
        mock_source_manager = Mock()
        mock_dest_manager = Mock()
        
        mock_source_artifact = Mock()
        mock_source_artifact.id = "artifact-1"
        mock_source_artifact.name = "Artifact 1"
        
        mock_source_list = Mock()
        mock_source_list.artifact_types = [mock_source_artifact]
        mock_source_manager.list_artifact_types.return_value = mock_source_list
        
        mock_dest_list = Mock()
        mock_dest_list.artifact_types = []
        mock_dest_manager.list_artifact_types.return_value = mock_dest_list
        
        mock_lab_manager.side_effect = [mock_source_manager, mock_dest_manager]
        
        comparator = ProjectComparator(
            from_api_key="src_key",
            from_instance="https://api.test.ai",
            from_project_id="proj-1",
            from_organization_id="org-1",
            to_api_key="dest_key",
            to_instance="https://api.prod.ai",
            to_project_id="proj-2",
            to_organization_id="org-2",
            resource_types=["artifact_types"]
        )
        
        diff = comparator.compare()
        
        self.assertIn("artifact_types", diff.resource_diffs)
        artifact_diff = diff.resource_diffs["artifact_types"]
        self.assertEqual(len(artifact_diff.only_in_source), 1)

    @patch('pygeai.migration.comparison.RAGAssistantMapper')
    @patch('pygeai.migration.comparison.RAGAssistantClient')
    @patch('pygeai.migration.comparison.AILabManager')
    def test_compare_rag_assistants(self, mock_lab_manager, mock_rag_client, mock_mapper):
        mock_source_manager = Mock()
        mock_dest_manager = Mock()
        mock_lab_manager.side_effect = [mock_source_manager, mock_dest_manager]
        
        mock_source_rag = Mock()
        mock_dest_rag = Mock()
        
        mock_assistant = Mock()
        mock_assistant.name = "Assistant 1"
        mock_mapper.map_to_rag_assistant.return_value = mock_assistant
        
        mock_source_rag.get_assistants_from_project.return_value = {
            "assistants": [{"name": "Assistant 1"}]
        }
        mock_dest_rag.get_assistants_from_project.return_value = {
            "assistants": []
        }
        
        mock_rag_client.side_effect = [mock_source_rag, mock_dest_rag]
        
        comparator = ProjectComparator(
            from_api_key="src_key",
            from_instance="https://api.test.ai",
            from_project_id="proj-1",
            from_organization_id="org-1",
            to_api_key="dest_key",
            to_instance="https://api.prod.ai",
            to_project_id="proj-2",
            to_organization_id="org-2",
            resource_types=["rag_assistants"]
        )
        
        diff = comparator.compare()
        
        self.assertIn("rag_assistants", diff.resource_diffs)
        rag_diff = diff.resource_diffs["rag_assistants"]
        self.assertEqual(len(rag_diff.only_in_source), 1)

    @patch('pygeai.migration.comparison.FileManager')
    @patch('pygeai.migration.comparison.AILabManager')
    def test_compare_files_with_org_ids(self, mock_lab_manager, mock_file_manager):
        mock_source_lab = Mock()
        mock_dest_lab = Mock()
        mock_lab_manager.side_effect = [mock_source_lab, mock_dest_lab]
        
        mock_source_file_mgr = Mock()
        mock_dest_file_mgr = Mock()
        
        mock_file = Mock()
        mock_file.id = "file-1"
        mock_file.filename = "test.txt"
        
        mock_source_list = Mock()
        mock_source_list.files = [mock_file]
        mock_source_file_mgr.get_file_list.return_value = mock_source_list
        
        mock_dest_list = Mock()
        mock_dest_list.files = []
        mock_dest_file_mgr.get_file_list.return_value = mock_dest_list
        
        mock_file_manager.side_effect = [mock_source_file_mgr, mock_dest_file_mgr]
        
        comparator = ProjectComparator(
            from_api_key="src_key",
            from_instance="https://api.test.ai",
            from_project_id="proj-1",
            to_api_key="dest_key",
            to_instance="https://api.prod.ai",
            to_project_id="proj-2",
            from_organization_id="org-1",
            to_organization_id="org-2",
            resource_types=["files"]
        )
        
        diff = comparator.compare()
        
        self.assertIn("files", diff.resource_diffs)
        file_diff = diff.resource_diffs["files"]
        self.assertEqual(len(file_diff.only_in_source), 1)

    @patch('pygeai.migration.comparison.AILabManager')
    def test_compare_files_without_org_ids_skips(self, mock_lab_manager):
        mock_source_lab = Mock()
        mock_dest_lab = Mock()
        mock_lab_manager.side_effect = [mock_source_lab, mock_dest_lab]
        
        comparator = ProjectComparator(
            from_api_key="src_key",
            from_instance="https://api.test.ai",
            from_project_id="proj-1",
            from_organization_id="org-1",
            to_api_key="dest_key",
            to_instance="https://api.prod.ai",
            to_project_id="proj-2",
            to_organization_id="org-2",
            resource_types=["files"]
        )
        
        diff = comparator.compare()
        
        self.assertIn("files", diff.resource_diffs)
        file_diff = diff.resource_diffs["files"]
        self.assertEqual(file_diff.total_source, 0)
        self.assertEqual(file_diff.total_destination, 0)

    @patch('pygeai.migration.comparison.UsageLimitManager')
    @patch('pygeai.migration.comparison.AILabManager')
    def test_compare_usage_limits_with_org_keys(self, mock_lab_manager, mock_limit_manager):
        mock_source_lab = Mock()
        mock_dest_lab = Mock()
        mock_lab_manager.side_effect = [mock_source_lab, mock_dest_lab]
        
        mock_source_limit_mgr = Mock()
        mock_dest_limit_mgr = Mock()
        
        mock_limit = Mock()
        mock_limit.model = "gpt-4"
        mock_limit.limit = 1000
        
        mock_source_response = Mock()
        mock_source_response.usage_limits = [mock_limit]
        mock_source_limit_mgr.get_all_usage_limits_from_project.return_value = mock_source_response
        
        mock_dest_response = Mock()
        mock_dest_response.usage_limits = []
        mock_dest_limit_mgr.get_latest_usage_limit_from_project.return_value = mock_dest_response
        
        mock_limit_manager.side_effect = [mock_source_limit_mgr, mock_dest_limit_mgr]
        
        comparator = ProjectComparator(
            from_api_key="src_key",
            from_instance="https://api.test.ai",
            from_project_id="proj-1",
            to_api_key="dest_key",
            to_instance="https://api.prod.ai",
            to_project_id="proj-2",
            from_organization_id="org-1",
            to_organization_id="org-2",
            from_organization_api_key="src_org_key",
            to_organization_api_key="dest_org_key",
            resource_types=["usage_limits"]
        )
        
        diff = comparator.compare()
        
        self.assertIn("usage_limits", diff.resource_diffs)
        limit_diff = diff.resource_diffs["usage_limits"]
        self.assertEqual(len(limit_diff.only_in_source), 1)

    @patch('pygeai.migration.comparison.AILabManager')
    def test_compare_usage_limits_without_org_keys_skips(self, mock_lab_manager):
        mock_source_lab = Mock()
        mock_dest_lab = Mock()
        mock_lab_manager.side_effect = [mock_source_lab, mock_dest_lab]
        
        comparator = ProjectComparator(
            from_api_key="src_key",
            from_instance="https://api.test.ai",
            from_project_id="proj-1",
            from_organization_id="org-1",
            to_api_key="dest_key",
            to_instance="https://api.prod.ai",
            to_project_id="proj-2",
            to_organization_id="org-2",
            resource_types=["usage_limits"]
        )
        
        diff = comparator.compare()
        
        self.assertIn("usage_limits", diff.resource_diffs)
        limit_diff = diff.resource_diffs["usage_limits"]
        self.assertEqual(limit_diff.total_source, 0)
        self.assertEqual(limit_diff.total_destination, 0)

    @patch('pygeai.migration.comparison.SecretClient')
    @patch('pygeai.migration.comparison.AILabManager')
    def test_compare_secrets(self, mock_lab_manager, mock_secret_client):
        mock_source_lab = Mock()
        mock_dest_lab = Mock()
        mock_lab_manager.side_effect = [mock_source_lab, mock_dest_lab]
        
        mock_source_secret = Mock()
        mock_dest_secret = Mock()
        
        mock_source_secret.list_secrets.return_value = {
            "secrets": [{"id": "secret-1", "name": "Secret 1"}]
        }
        mock_dest_secret.list_secrets.return_value = {
            "secrets": []
        }
        
        mock_secret_client.side_effect = [mock_source_secret, mock_dest_secret]
        
        comparator = ProjectComparator(
            from_api_key="src_key",
            from_instance="https://api.test.ai",
            from_project_id="proj-1",
            from_organization_id="org-1",
            to_api_key="dest_key",
            to_instance="https://api.prod.ai",
            to_project_id="proj-2",
            to_organization_id="org-2",
            resource_types=["secrets"]
        )
        
        diff = comparator.compare()
        
        self.assertIn("secrets", diff.resource_diffs)
        secret_diff = diff.resource_diffs["secrets"]
        self.assertEqual(len(secret_diff.only_in_source), 1)

    @patch('pygeai.migration.comparison.SecretClient')
    @patch('pygeai.migration.comparison.AILabManager')
    def test_full_comparison_all_resources(self, mock_lab_manager, mock_secret_client):
        mock_source_lab = Mock()
        mock_dest_lab = Mock()
        
        mock_source_lab.list_agents.return_value = Mock(agents=[])
        mock_source_lab.list_tools.return_value = Mock(tools=[])
        mock_source_lab.list_processes.return_value = Mock(processes=[])
        mock_source_lab.list_tasks.return_value = Mock(tasks=[])
        mock_source_lab.list_artifact_types.return_value = Mock(artifact_types=[])
        
        mock_dest_lab.list_agents.return_value = Mock(agents=[])
        mock_dest_lab.list_tools.return_value = Mock(tools=[])
        mock_dest_lab.list_processes.return_value = Mock(processes=[])
        mock_dest_lab.list_tasks.return_value = Mock(tasks=[])
        mock_dest_lab.list_artifact_types.return_value = Mock(artifact_types=[])
        
        mock_lab_manager.side_effect = [mock_source_lab, mock_dest_lab]
        
        mock_source_secret = Mock()
        mock_dest_secret = Mock()
        mock_source_secret.list_secrets.return_value = {"secrets": []}
        mock_dest_secret.list_secrets.return_value = {"secrets": []}
        mock_secret_client.side_effect = [mock_source_secret, mock_dest_secret]
        
        comparator = ProjectComparator(
            from_api_key="src_key",
            from_instance="https://api.test.ai",
            from_project_id="proj-1",
            from_organization_id="org-1",
            to_api_key="dest_key",
            to_instance="https://api.prod.ai",
            to_project_id="proj-2",
            to_organization_id="org-2",
            resource_types=["agents", "tools", "processes", "tasks", "artifact_types", "secrets"]
        )
        
        diff = comparator.compare()
        
        self.assertEqual(len(diff.resource_diffs), 6)
        self.assertIn("agents", diff.resource_diffs)
        self.assertIn("tools", diff.resource_diffs)
        self.assertIn("processes", diff.resource_diffs)
        self.assertIn("tasks", diff.resource_diffs)
        self.assertIn("artifact_types", diff.resource_diffs)
        self.assertIn("secrets", diff.resource_diffs)

    @patch('pygeai.migration.comparison.AILabManager')
    def test_filtered_resource_types_agents_only(self, mock_lab_manager):
        mock_source_lab = Mock()
        mock_dest_lab = Mock()
        
        mock_source_lab.list_agents.return_value = Mock(agents=[])
        mock_dest_lab.list_agents.return_value = Mock(agents=[])
        
        mock_lab_manager.side_effect = [mock_source_lab, mock_dest_lab]
        
        comparator = ProjectComparator(
            from_api_key="src_key",
            from_instance="https://api.test.ai",
            from_project_id="proj-1",
            from_organization_id="org-1",
            to_api_key="dest_key",
            to_instance="https://api.prod.ai",
            to_project_id="proj-2",
            to_organization_id="org-2",
            resource_types=["agents"]
        )
        
        diff = comparator.compare()
        
        self.assertEqual(len(diff.resource_diffs), 1)
        self.assertIn("agents", diff.resource_diffs)
        self.assertNotIn("tools", diff.resource_diffs)


class TestDiffFormatter(unittest.TestCase):
    def setUp(self):
        self.formatter = DiffFormatter()
        self.sample_diff = ProjectDiff(
            source_project_id="proj-1",
            destination_project_id="proj-2",
            source_instance="https://api.test.ai",
            destination_instance="https://api.prod.ai",
            timestamp="2026-02-02T12:00:00",
            summary={"resource_types_compared": 2, "total_differences": 3}
        )
        
        self.sample_diff.resource_diffs["agents"] = ResourceDiff(
            resource_type="agents",
            only_in_source=[{"id": "agent-1", "name": "Agent 1"}],
            only_in_destination=[{"id": "agent-2", "name": "Agent 2"}],
            in_both=[{"id": "agent-3", "name": "Agent 3"}],
            total_source=2,
            total_destination=2
        )

    def test_format_as_text_basic(self):
        result = self.formatter.format_as_text(self.sample_diff)
        
        self.assertIn("PROJECT COMPARISON REPORT", result)
        self.assertIn("proj-1", result)
        self.assertIn("proj-2", result)
        self.assertIn("AGENTS", result)
        self.assertIn("Agent 1", result)
        self.assertIn("Agent 2", result)

    def test_format_as_text_no_differences(self):
        diff = ProjectDiff(
            source_project_id="proj-1",
            destination_project_id="proj-2",
            source_instance="https://api.test.ai",
            destination_instance="https://api.prod.ai",
            summary={"resource_types_compared": 0, "total_differences": 0}
        )
        
        result = self.formatter.format_as_text(diff)
        
        self.assertIn("Total differences found: 0", result)

    def test_format_as_json(self):
        result = self.formatter.format_as_json(self.sample_diff)
        
        data = json.loads(result)
        self.assertEqual(data["source_project_id"], "proj-1")
        self.assertEqual(data["destination_project_id"], "proj-2")
        self.assertIn("resource_diffs", data)
        self.assertIn("agents", data["resource_diffs"])

    def test_format_as_json_valid_structure(self):
        result = self.formatter.format_as_json(self.sample_diff)
        
        data = json.loads(result)
        self.assertIn("summary", data)
        self.assertIn("timestamp", data)
        self.assertIn("resource_diffs", data)
        self.assertEqual(data["summary"]["total_differences"], 3)

    def test_format_as_markdown(self):
        result = self.formatter.format_as_markdown(self.sample_diff)
        
        self.assertIn("# Project Comparison Report", result)
        self.assertIn("## Agents", result)
        self.assertIn("| Metric | Count |", result)
        self.assertIn("Agent 1", result)
        self.assertIn("Agent 2", result)

    def test_format_as_markdown_tables(self):
        result = self.formatter.format_as_markdown(self.sample_diff)
        
        self.assertIn("|--------|-------|", result)
        self.assertIn("| Source | 2 |", result)
        self.assertIn("| Destination | 2 |", result)

    def test_write_to_file(self):
        with tempfile.TemporaryDirectory() as tmpdir:
            filepath = os.path.join(tmpdir, "test_report.txt")
            content = "Test content"
            
            self.formatter.write_to_file(content, filepath)
            
            self.assertTrue(os.path.exists(filepath))
            with open(filepath, 'r') as f:
                read_content = f.read()
            self.assertEqual(read_content, content)

    def test_write_to_file_creates_directory(self):
        with tempfile.TemporaryDirectory() as tmpdir:
            filepath = os.path.join(tmpdir, "subdir", "test_report.txt")
            content = "Test content"
            
            self.formatter.write_to_file(content, filepath)
            
            self.assertTrue(os.path.exists(filepath))
            with open(filepath, 'r') as f:
                read_content = f.read()
            self.assertEqual(read_content, content)


if __name__ == '__main__':
    unittest.main()
