import logging
from dataclasses import dataclass, asdict
from datetime import datetime
import json
import os

@dataclass
class SimulationResult:
    """Results from simulating an action"""
    scenario: str
    predicted_outcome: str
    confidence: float
    risks: list[str]
    alternatives: list[str]
    timestamp: str = datetime.now().isoformat()

class WorldModelSimulator:
    """
    Simulates actions to predict consequences before execution
    Helps make informed decisions by simulating scenarios
    """
    
    def __init__(self, log_dir="/Eden/LOGS/decision_making"):
        """Initialize world model simulator"""
        self.log_dir = log_dir
        os.makedirs(self.log_dir, exist_ok=True)
        
        # Initialize logging
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            handlers=[
                logging.FileHandler(os.path.join(log_dir, "world_model.log")),
                logging.StreamHandler()
            ]
        )
        self.logger = logging.getLogger(__name__)
        
        # Model parameters
        self.model_version = "1.0"
        self.prediction_horizon = 5  # How many steps ahead to simulate
    
    def simulate_scenario(self, scenario: str) -> SimulationResult:
        """
        Simulates a given scenario and predicts outcomes
        
        Args:
            scenario: Description of the action/scenario to simulate
            
        Returns:
            SimulationResult containing predicted outcome and analysis
        """
        try:
            # Step 1: Break down scenario into components
            components = self._breakdown_scenario(scenario)
            
            # Step 2: Simulate short-term outcomes
            immediate_outcome = self._simulate_immediate(components)
            
            # Step 3: Simulate long-term effects
            long_term_outcome = self._simulate_longterm(components)
            
            # Step 4: Assess risks and alternatives
            risks = self._assess_risks(components, immediate_outcome, long_term_outcome)
            alternatives = self._suggest_alternatives(components)
            confidence = self._calculate_confidence(risks, alternatives)
            
            # Combine predictions
            predicted_outcome = f"Immediate: {immediate_outcome}\nLong-term: {long_term_outcome}"
            
            return SimulationResult(
                scenario=scenario,
                predicted_outcome=predicted_outcome,
                confidence=confidence,
                risks=risks,
                alternatives=alternatives
            )
        except Exception as e:
            self.logger.error(f"Failed to simulate scenario: {e}")
            raise
    
    def _breakdown_scenario(self, scenario: str) -> dict:
        """
        Breaks down a scenario into component parts
        
        Args:
            scenario: Description of action/scenario
            
        Returns:
            Dictionary of scenario components
        """
        # Simple text analysis for component identification
        components = {
            "objective": self._extract_objective(scenario),
            "impacts": self._identify_impacts(scenario),
            "dependencies": self._identify_dependencies(scenario),
            "time_scale": self._assess_time_scale(scenario)
        }
        return components
    
    def _extract_objective(self, scenario: str) -> str:
        """Extracts the primary objective from scenario"""
        # Simple extraction - can be enhanced
        words = scenario.split()
        for i, word in enumerate(words):
            if word.lower() in ["objective", "goal", "purpose"]:
                return ' '.join(words[i+1:i+3]).capitalize()
        return "Unknown Objective"
    
    def _identify_impacts(self, scenario: str) -> list[str]:
        """Identifies all impacts of the scenario"""
        # Keywords indicating impacts
        impact_keywords = ["impact", "effect", "result", "consequence", "outcome"]
        impacts = []
        words = scenario.lower().split()
        
        i = 0
        while i < len(words):
            if words[i] in impact_keywords:
                # Capture next phrase as impact
                impact = ' '.join(words[i+1:i+4]).capitalize()
                impacts.append(impact)
                i += 4  # Skip captured phrase
            else:
                i += 1
                
        return impacts
    
    def _identify_dependencies(self, scenario: str) -> list[str]:
        """Identifies dependencies and prerequisites"""
        # Capture keywords indicating dependencies
        dependency_keywords = ["depend", "require", "need", "prerequisite"]
        words = scenario.lower().split()
        dependencies = []
        
        for i, word in enumerate(words):
            if word in dependency_keywords:
                # Capture next phrase as dependency
                dep = ' '.join(words[i+1:i+3]).capitalize()
                dependencies.append(dep)
                
        return dependencies
    
    def _assess_time_scale(self, scenario: str) -> str:
        """Assesses the time scale of impacts"""
        # Simple heuristic for time scale
        words = scenario.split()
        if "short" in words or "immediate" in words:
            return "Short-term (<= 1 week)"
        elif "medium" in words or "future" in words:
            return "Medium-term (1-3 months)"
        elif "long" in words or "permanent" in words:
            return "Long-term (>= 6 months)"
        else:
            return "Unknown time scale"
    
    def _simulate_immediate(self, components: dict) -> str:
        """Simulates immediate outcomes"""
        # Return simple prediction based on components
        impacts = components["impacts"]
        if not impacts:
            return "No immediate impact predicted"
            
        return f"Immediate impact: {impacts[0]}"
    
    def _simulate_longterm(self, components: dict) -> str:
        """Simulates long-term outcomes"""
        # Consider multiple scenarios for long-term
        time_scale = components["time_scale"]
        alternatives = self._suggest_alternatives(components)
        
        if not alternatives:
            return "Insufficient info for long-term prediction"
            
        best_alternative = alternatives[0]
        worst_alternative = alternatives[-1]
        
        return f"Long-term trend: {best_alternative} (best case), {worst_alternative} (worst case)"
    
    def _assess_risks(self, components: dict, 
                      immediate: str, long_term: str) -> list[str]:
        """Assesses risks associated with scenario"""
        risks = []
        
        # Identify risk factors
        if "blockchain" in components.get("objective", "").lower():
            risks.append("Gas costs can be high")
        if "deployment" in components.get("objective", "").lower():
            risks.append("Dependency on external services")
            
        # Consider impact on ecosystem
        impacts = components["impacts"]
        for impact in impacts:
            if "security" in impact.lower():
                risks.append("Security breach risk exists")
            if "efficiency" in impact.lower():
                risks.append("May affect transaction times")
                
        return risks
    
    def _suggest_alternatives(self, components: dict) -> list[str]:
        """Suggests alternative approaches"""
        alternatives = []
        
        # Simple alternative generation
        current_approach = components.get("objective", "Unknown Objective")
        
        if "smart contract" in current_approach.lower():
            alternatives.append(f"Manual deployment by developer")
            alternatives.append(f"Use of deploy service like Foundry")
            
        if "optimization" in current_approach.lower():
            alternatives.append(f"Parallel testing and review")
            alternatives.append(f"Automated user testing with testnet")
            
        return alternatives[:2]  # Return top 2
    
    def _calculate_confidence(self, risks: list[str], 
                            alternatives: list[str]) -> float:
        """Calculates prediction confidence"""
        if not risks and not alternatives:
            return 0.5
        
        risk_count = len(risks)
        alt_count = len(alternatives)
        
        # Confidence decreases with risks
        base_confidence = 0.7 - (risk_count * 0.1)
        base_confidence = max(0.3, base_confidence)  # Min 30%
        
        # Alternatives increase confidence
        alt_bonus = alt_count * 0.1
        confidence = min(1.0, base_confidence + alt_bonus)
        
        return round(confidence, 2)
    
    def save_simulation(self, result: SimulationResult, filename_prefix: str = "") -> str:
        """
        Saves simulation results to file
        
        Args:
            result: SimulationResult to save
            filename_prefix: Optional prefix for filename
            
        Returns:
            Path where result was saved
        """
        # Create unique filename
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        if filename_prefix:
            filename = f"{filename_prefix}_{timestamp}.json"
        else:
            filename = f"simulation_{timestamp}.json"
        filepath = os.path.join(self.log_dir, filename)
        
        # Convert dataclass to dict for JSON
        data = asdict(result)
        
        try:
            with open(filepath, 'w') as f:
                json.dump(data, f, indent=2)
            self.logger.info(f"Saved simulation results to {filepath}")
            return filepath
        except Exception as e:
            self.logger.error(f"Failed to save simulation: {e}")
            raise
    
    def load_simulation(self, filename: str) -> SimulationResult:
        """
        Loads a previous simulation result
        
        Args:
            filename: Name of file to load
            
        Returns:
            Loaded SimulationResult
        """
        filepath = os.path.join(self.log_dir, filename)
        
        try:
            with open(filepath, 'r') as f:
                data = json.load(f)
            # Convert dict to SimulationResult
            return SimulationResult(**data)
        except FileNotFoundError:
            self.logger.error(f"Simulation not found: {filepath}")
            raise
        except Exception as e:
            self.logger.error(f"Failed to load simulation: {e}")
            raise

if __name__ == "__main__":
    # Example usage
    import sys
    
    def main():
        simulator = WorldModelSimulator()
        
        # Simulate simple scenario
        scenario = "Deploy smart contract to Ethereum blockchain"
        result = simulator.simulate_scenario(scenario)
        
        print(f"\n{'='*50}")
        print("Simulation Results:")
        print(f"{'='*50}\n")
        print(f"Scenario: {result.scenario}")
        print(f"\nPredicted Outcome:")
        print(f"{result.predicted_outcome}")
        print(f"\nConfidence: {result.confidence * 100:.1f}%")
        
        if result.risks:
            print("\nRisks:")
            for i, risk in enumerate(result.risks, 1):
                print(f"  {i}. {risk}")
                
        if result.alternatives:
            print("\nAlternatives:")
            for i, alt in enumerate(result.alternatives, 1):
                print(f"  {i}. {alt}")
                
        # Save results
        try:
            saved_path = simulator.save_simulation(result, filename_prefix="deploy_contract")
            print(f"\nResults saved to: {saved_path}")
        except Exception as e:
            print(f"\nError saving results: {e}")
    
    if len(sys.argv) > 1:
        scenario = ' '.join(sys.argv[1:])
        main()
    else:
        print("Usage: python world_model_simulator.py <scenario_description>")