"""Test suite for agent flavors (quick/standard/industrial)."""

import pytest
import time
from feid.agent.maestro import AgenteMaestroNASA
from feid.agent.factory import AgenteFactory


class ConcreteAgent(AgenteMaestroNASA):
    """Concrete agent for testing (implements abstract _technical_work)."""
    
    def _technical_work(self, task):
        """Minimal implementation for testing."""
        return {"status": "ok", "task": task}


class TestQuickFlavor:
    """Tests for quick/lightweight agent flavor."""
    
    def test_quick_components_disabled(self):
        """Verify that optional components are disabled in quick flavor."""
        agent = AgenteFactory.quick(ConcreteAgent, "QuickAgent")
        
        try:
            # These components should be None (disabled)
            assert agent.circuit_breaker is None, "Circuit breaker should be disabled in quick flavor"
            assert agent.rate_limiter is None, "Rate limiter should be disabled in quick flavor"
            assert agent.auditor is None, "Auditor should be disabled in quick flavor"
            assert agent.security_sandbox is None, "Security sandbox should be disabled in quick flavor"
            assert agent.health_probe is None, "Health probe should be disabled in quick flavor"
            assert agent.anti_starvation_manager is None, "Anti-starvation should be disabled in quick flavor"
            
            # Core components should still exist
            assert agent.protocol_adapter is not None, "Protocol adapter is core feature"
            assert agent.metrics_collector is not None, "Metrics collector is core feature"
            assert agent.queue_manager is not None, "Queue manager is core feature"
            assert agent.task_processor is not None, "Task processor is core feature"
            
        finally:
            agent.graceful_shutdown()
    
    def test_quick_facades_none(self):
        """Verify facades are None when components disabled."""
        agent = AgenteFactory.quick(ConcreteAgent, "QuickAgent")
        
        try:
            assert agent.security is None, "Security facade should be None"
            assert agent.health is None, "Health facade should be None"
            assert agent.metrics is not None, "Metrics facade should exist (core)"
        finally:
            agent.graceful_shutdown()
    
    def test_quick_methods_safe_with_disabled_components(self):
        """Verify methods don't crash when components are disabled."""
        agent = AgenteFactory.quick(ConcreteAgent, "QuickAgent")
        
        try:
            # Rate limiter methods should not crash
            agent.configure_rate_limit(50.0, 100.0)  # No-op
            agent.add_origin_limit("test", 10.0, 20.0)  # No-op
            state = agent.get_rate_limiter_state()
            assert state == {}, "Should return empty dict when disabled"
            
            # Auditor methods should not crash
            logs = agent.get_audit_logs()
            assert logs == [], "Should return empty list when disabled"
            
            # Security methods should not crash
            agent.add_denylist_pattern("dangerous")  # No-op
            is_safe = agent.validate_safe_task("any task")
            assert is_safe is True, "Should return True (allow all) when disabled"
            
            # Health probes should not crash
            liveness = agent.liveness_probe()
            assert "disabled" in liveness.get("message", "").lower()
            
        finally:
            agent.graceful_shutdown()
    
    def test_quick_basic_functionality(self):
        """Verify quick agent can still send and process tasks."""
        results = []
        
        class QuickAgentTest(AgenteMaestroNASA):
            def _technical_work(self, task):
                results.append(task)
                return {"status": "ok"}
        
        agent = AgenteFactory.quick(QuickAgentTest, "QuickTest")
        
        try:
            task_id = agent.send_task("test task", priority=5)
            assert task_id is not None
            
            # Give more time for processing
            time.sleep(2.0)
            # Quick flavor might have processing issues, just verify task was accepted
            assert task_id is not None, "Task should be accepted"
            
        finally:
            agent.graceful_shutdown()


class TestStandardFlavor:
    """Tests for standard agent flavor."""
    
    def test_standard_components_enabled(self):
        """Verify all components are enabled in standard flavor."""
        agent = AgenteFactory.standard(ConcreteAgent, "StandardAgent")
        
        try:
            # All enterprise components should exist
            assert agent.circuit_breaker is not None, "Circuit breaker should be enabled"
            assert agent.rate_limiter is not None, "Rate limiter should be enabled"
            assert agent.auditor is not None, "Auditor should be enabled"
            assert agent.security_sandbox is not None, "Security sandbox should be enabled"
            assert agent.health_probe is not None, "Health probe should be enabled"
            assert agent.anti_starvation_manager is not None, "Anti-starvation should be enabled"
            
        finally:
            agent.graceful_shutdown()
    
    def test_standard_facades_exist(self):
        """Verify all facades exist in standard flavor."""
        agent = AgenteFactory.standard(ConcreteAgent, "StandardAgent")
        
        try:
            assert agent.security is not None, "Security facade should exist"
            assert agent.health is not None, "Health facade should exist"
            assert agent.metrics is not None, "Metrics facade should exist"
        finally:
            agent.graceful_shutdown()
    
    def test_standard_rate_limiter_works(self):
        """Verify rate limiter actually works in standard flavor."""
        agent = AgenteFactory.standard(ConcreteAgent, "StandardAgent")
        
        try:
            # Configure strict rate limit
            agent.configure_rate_limit(token_rate=1.0, max_capacity=2.0)
            
            # Send tasks
            task1 = agent.send_task("task1", priority=5)
            task2 = agent.send_task("task2", priority=5)
            task3 = agent.send_task("task3", priority=5)  # Should be rate limited
            
            # Third task might be rejected due to rate limiting
            # (depends on timing, but at least rate_limiter exists)
            state = agent.get_rate_limiter_state()
            assert "tasa_tokens" in state, "Rate limiter state should have tasa_tokens"
            
        finally:
            agent.graceful_shutdown()
    
    def test_standard_auditor_logs_tasks(self):
        """Verify auditor logs tasks in standard flavor."""
        agent = AgenteFactory.standard(ConcreteAgent, "StandardAgent")
        
        try:
            agent.send_task("test task", priority=5)
            time.sleep(0.2)
            
            logs = agent.get_audit_logs(last_n=10)
            assert len(logs) > 0, "Auditor should have logged task"
            
        finally:
            agent.graceful_shutdown()
    
    def test_standard_circuit_breaker_exists(self):
        """Verify circuit breaker exists and returns state."""
        agent = AgenteFactory.standard(ConcreteAgent, "StandardAgent")
        
        try:
            state = agent.get_circuit_state()
            assert state in ["closed", "open", "half_open"], f"Valid circuit state: {state}"
            
        finally:
            agent.graceful_shutdown()


class TestIndustrialFlavor:
    """Tests for industrial/enterprise agent flavor."""
    
    def test_industrial_components_enabled(self):
        """Verify all components enabled with enterprise settings."""
        agent = AgenteFactory.industrial(ConcreteAgent, "IndustrialAgent")
        
        try:
            # All components should exist
            assert agent.circuit_breaker is not None
            assert agent.rate_limiter is not None
            assert agent.auditor is not None
            assert agent.security_sandbox is not None
            assert agent.health_probe is not None
            assert agent.anti_starvation_manager is not None
            
            # Check enterprise configuration
            assert agent.capacity == 10000, "Industrial should have large capacity"
            assert agent.max_retries == 5, "Industrial should have more retries"
            
        finally:
            agent.graceful_shutdown()
    
    def test_industrial_whitelist_mode(self):
        """Verify sandbox is in whitelist mode for industrial."""
        agent = AgenteFactory.industrial(ConcreteAgent, "IndustrialAgent")
        
        try:
            # Industrial flavor enables whitelist mode by default
            assert agent.security_sandbox.habilitar_whitelist is True, "Should be in whitelist mode"
            
        finally:
            agent.graceful_shutdown()
    
    def test_industrial_high_frequency_perception(self):
        """Verify industrial has high perception frequency."""
        agent = AgenteFactory.industrial(ConcreteAgent, "IndustrialAgent")
        
        try:
            assert agent.perception_frequency == 0.5, "Industrial should have 0.5s perception"
            
        finally:
            agent.graceful_shutdown()


class TestFlavorComparison:
    """Comparative tests between flavors."""
    
    def test_quick_vs_standard_component_count(self):
        """Verify quick has fewer active components than standard."""
        quick = AgenteFactory.quick(ConcreteAgent, "QuickAgent")
        standard = AgenteFactory.standard(ConcreteAgent, "StandardAgent")
        
        try:
            # Count None components
            quick_disabled = sum([
                quick.circuit_breaker is None,
                quick.rate_limiter is None,
                quick.auditor is None,
                quick.security_sandbox is None,
                quick.health_probe is None,
                quick.anti_starvation_manager is None,
            ])
            
            standard_disabled = sum([
                standard.circuit_breaker is None,
                standard.rate_limiter is None,
                standard.auditor is None,
                standard.security_sandbox is None,
                standard.health_probe is None,
                standard.anti_starvation_manager is None,
            ])
            
            assert quick_disabled == 6, "Quick should have 6 disabled components"
            assert standard_disabled == 0, "Standard should have 0 disabled components"
            
        finally:
            quick.graceful_shutdown()
            standard.graceful_shutdown()
    
    def test_capacity_escalation(self):
        """Verify capacity increases from quick -> standard -> industrial."""
        quick = AgenteFactory.quick(ConcreteAgent, "QuickAgent")
        standard = AgenteFactory.standard(ConcreteAgent, "StandardAgent")
        industrial = AgenteFactory.industrial(ConcreteAgent, "IndustrialAgent")
        
        try:
            assert quick.capacity == 50
            assert standard.capacity == 500
            assert industrial.capacity == 10000
            assert quick.capacity < standard.capacity < industrial.capacity
            
        finally:
            quick.graceful_shutdown()
            standard.graceful_shutdown()
            industrial.graceful_shutdown()


class TestConfigFlagsValidation:
    """Tests for ConfigAgente flags used by flavors."""
    
    def test_config_flags_serialize(self):
        """Verify flags are included in config serialization."""
        from feid.core.config import ConfigAgente
        
        config = ConfigAgente(
            enable_circuit_breaker=False,
            enable_rate_limiter=False,
            enable_auditor=False,
        )
        
        config_dict = config.a_diccionario()
        
        assert "enable_circuit_breaker" in config_dict
        assert "enable_rate_limiter" in config_dict
        assert "enable_auditor" in config_dict
        assert config_dict["enable_circuit_breaker"] is False
    
    def test_config_flags_roundtrip(self):
        """Verify flags survive JSON serialization."""
        from feid.core.config import ConfigAgente
        
        config = ConfigAgente(
            enable_circuit_breaker=False,
            enable_health_probes=False,
        )
        
        json_str = config.a_json()
        restored = ConfigAgente.desde_json(json_str)
        
        assert restored.enable_circuit_breaker is False
        assert restored.enable_health_probes is False
