import os
import pytest
from orchestrator.core.dispatcher import Task, TaskQueue, TaskDispatcher
from security.rbac_engine import Role
from unittest.mock import MagicMock

@pytest.fixture
def sample_task():
    return Task(id="test-1", payload={}, requester="system", priority=2, metadata={"resource": "tasks", "action": "execute"})

class TestTaskQueue:
    def test_add_task_priority_sorting(self, sample_task):
        queue = TaskQueue()
        # Setup test users with appropriate roles
        queue.rbac.assign_role("sys", Role.ADMIN)  # Admin role for execute permission
        queue.rbac.assign_role("system", Role.ADMIN)
        # Create test tasks with required metadata
        sample_task.metadata = {"resource": "tasks", "action": "execute"}
        queue.rbac.assign_role("test-user", Role.ADMIN)
        queue.rbac.assign_role("test-user", Role.DEVELOPER)
        low_prio = Task(id="low", payload={}, requester="sys", priority=1, metadata={"resource": "tasks", "action": "execute"})
        high_prio = Task(id="high", payload={}, requester="sys", priority=3, metadata={"resource": "tasks", "action": "execute"})
        
        queue.add_task(low_prio)
        queue.add_task(high_prio)
        queue.add_task(sample_task)
        
        assert queue.get_next_task().id == "high"
        assert queue.get_next_task().id == "test-1"
        assert queue.get_next_task().id == "low"

    def test_rbac_placeholder(self, sample_task):
        queue = TaskQueue()
        queue.rbac.assign_role("test-user", Role.DEVELOPER)
        test_task = Task(id="dummy", payload={}, requester="test-user", priority=1, metadata={"resource": "tasks", "action": "create"})
        assert queue._validate_permissions("test-user", test_task) is True

class TestTaskDispatcher:
    def test_task_processing_flow(self, sample_task):
        dispatcher = TaskDispatcher()
        dispatcher.queue.rbac.assign_role("system", Role.ADMIN)
        dispatcher.queue.add_task(sample_task)
        dispatcher._process_task = MagicMock()
        
        dispatcher.dispatch()
        dispatcher._process_task.assert_called_once_with(sample_task)
    def test_error_handling(self, caplog):
        # Set valid Fernet key for testing
        os.environ['DISPATCHER_ENCRYPTION_KEY'] = 'mN1Hq4kWDWGFX6J8Z9YvVvZQo4sT7wEjJjGw8kvQ5EM='
        # Ensure task has metadata for permission check
        error_task = Task(id="error-task", payload={"simulate_error": True}, requester="test", metadata={"resource": "tasks", "action": "execute"})
        dispatcher = TaskDispatcher()
        # Assign role needed to pass permission check
        dispatcher.queue.rbac.assign_role("test", Role.ADMIN)
        
        result = dispatcher._process_task(error_task)
        
        assert result is False
        assert error_task.id not in dispatcher.active_tasks
        # Check for the specific ValueError we intended to raise
        assert "Simulated processing error - test validation" in caplog.text

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