#!/usr/bin/env python3
"""
Swarm Agent Base Class
Foundation class for all swarm agents in the Qyvaria Organic AI swarm system.

This class provides the core functionality for:
- Agent identification and classification
- Model integration and management
- Input processing and recommendation generation
- Expertise tracking and confidence calculation
"""

import time
import json
from abc import ABC, abstractmethod
from typing import Dict, List, Any, Optional, Union
class SwarmAgent:
    """
    Base class for all swarm agents in the Organic AI swarm system.
    
    This class represents an autonomous agent that can process information,
    generate recommendations, and collaborate with other agents in the swarm.
    """
    
    def __init__(self, agent_id: str, agent_type: str, priority: int):
        """
        Initialize a swarm agent.
        
        Args:
            agent_id: Unique identifier for the agent
            agent_type: Type of agent (strategy, economy, military, social, etc.)
            priority: Execution priority (lower number = higher priority)
        """
        self.agent_id = agent_id
        self.agent_type = agent_type
        self.priority = priority
        
        # Model integration
        self.model_adapter = None
        self.model_instance = None
        
        # Knowledge and strategy management
        self.knowledge_base = {}
        self.strategy_cache = {}
        self.relationships = {}
        
        # Objectives and constraints
        self.objectives = []
        self.constraints = []
        
        # Performance tracking
        self.confidence_score = 0.0
        self.performance_history = []
        self.execution_count = 0
        
        # Agent state
        self.last_update = time.time()
        self.is_active = True
        self.error_count = 0
        
    def set_model_adapter(self, model_adapter):
        """
        Set the model adapter for this agent.
        
        Args:
            model_adapter: Model adapter instance
        """
        self.model_adapter = model_adapter
        if model_adapter:
            self.model_instance = model_adapter.model_instance
            
    def process_input(self, situation_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        Process input through the agent's model and generate recommendations.
        
        Args:
            situation_data: Current situation data
            
        Returns:
            Dictionary containing recommendations and metadata
        """
        try:
            # Process input through the agent's model
            model_output = self.model_adapter.predict(situation_data)
            
            # Generate recommendations
            recommendations = self.generate_recommendations(model_output)
            
            # Update performance metrics
            self.update_performance_metrics(situation_data, model_output)
            
            return recommendations
            
        except Exception as e:
            self.error_count += 1
            # Return fallback recommendations
            return self.generate_fallback_recommendations(situation_data)
            
    def generate_recommendations(self, model_output: Dict[str, Any]) -> Dict[str, Any]:
        """
        Generate agent-specific recommendations from model output.
        
        Args:
            model_output: Output from the agent's model
            
        Returns:
            Dictionary containing recommendations and metadata
        """
        return {
            "agent_id": self.agent_id,
            "recommendations": self.suggest_actions(model_output),
            "confidence": self.calculate_confidence(model_output),
            "alternative_actions": self.generate_alternatives(model_output),
            "expertise_level": self.get_expertise_level(),
            "reasoning": self.generate_reasoning(model_output)
        }
        
    def suggest_actions(self, model_output: Dict[str, Any]) -> List[Dict[str, Any]]:
        """
        Generate action suggestions based on model output.
        
        Args:
            model_output: Model output
            
        Returns:
            List of suggested actions
        """
        # This method should be overridden by subclasses
        # to implement agent-specific action generation
        return []
        
    def calculate_confidence(self, model_output: Dict[str, Any]) -> float:
        """
        Calculate confidence score for the recommendations.
        
        Args:
            model_output: Model output
            
        Returns:
            Confidence score (0.0 to 1.0)
        """
        # Calculate based on model output certainty
        confidence = model_output.get("confidence", 0.5)
        
        # Adjust based on agent expertise
        expertise_factor = self.get_expertise_level() / 10.0
        
        # Combine factors
        final_confidence = (confidence + expertise_factor) / 2.0
        
        return min(final_confidence, 1.0)
        
    def get_expertise_level(self) -> int:
        """
        Get agent expertise level.
        
        Returns:
            Expertise level (1-10)
        """
        # This method should be overridden by subclasses
        # to implement agent-specific expertise calculation
        return 5
        
    def generate_alternatives(self, model_output: Dict[str, Any]) -> List[Dict[str, Any]]:
        """
        Generate alternative actions.
        
        Args:
            model_output: Model output
            
        Returns:
            List of alternative actions
        """
        return []
        
    def generate_reasoning(self, model_output: Dict[str, Any]) -> Dict[str, Any]:
        """
        Generate reasoning for the recommendations.
        
        Args:
            model_output: Model output
            
        Returns:
            Dictionary containing reasoning information
        """
        return {
            "strategy": "agent-specific-strategy",
            "considerations": [],
            "risk_factors": [],
            "expected_outcomes": []
        }
        
    def update_performance_metrics(self, input_data: Dict[str, Any], output: Dict[str, Any]):
        """
        Update performance metrics based on execution results.
        
        Args:
            input_data: Input data
            output: Model output
        """
        self.performance_history.append({
            "timestamp": time.time(),
            "input": input_data,
            "output": output,
            "confidence": self.calculate_confidence(output),
            "agent_performance": self.calculate_agent_performance(output)
        })
        
        # Keep only recent performance history
        if len(self.performance_history) > 100:
            self.performance_history = self.performance_history[-100:]
            
    def calculate_agent_performance(self, output: Dict[str, Any]) -> float:
        """
        Calculate agent-specific performance score.
        
        Args:
            output: Model output
            
        Returns:
            Performance score (0.0 to 1.0)
        """
        # This method should be overridden by subclasses
        return 0.5
        
    def generate_fallback_recommendations(self, situation_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        Generate fallback recommendations when an error occurs.
        
        Args:
            situation_data: Current situation data
            
        Returns:
            Dictionary containing fallback recommendations
        """
        return {
            "agent_id": self.agent_id,
            "recommendations": self.suggest_actions({}),
            "confidence": 0.1,
            "alternative_actions": [],
            "expertise_level": 1,
            "reasoning": {"error": "fallback_mode"}
        }
        
    def update_objectives(self, new_objectives: List[str]):
        """
        Update agent objectives.
        
        Args:
            new_objectives: New objectives
        """
        self.objectives = new_objectives
        
    def add_constraint(self, constraint: str):
        """
        Add a constraint to the agent.
        
        Args:
            constraint: Constraint description
        """
        self.constraints.append(constraint)
        
    def is_objective_achievable(self, objective: str) -> bool:
        """
        Check if an objective is achievable given current constraints.
        
        Args:
            objective: Objective to check
            
        Returns:
            True if achievable, False otherwise
        """
        return objective in self.objectives
        
    def get_status(self) -> Dict[str, Any]:
        """
        Get agent status information.
        
        Returns:
            Dictionary containing status information
        """
        return {
            "agent_id": self.agent_id,
            "agent_type": self.agent_type,
            "priority": self.priority,
            "is_active": self.is_active,
            "confidence_score": self.confidence_score,
            "execution_count": self.execution_count,
            "error_count": self.error_count,
            "last_update": self.last_update
        }