"""
Eden Self-Modifier v2 - FIXED
- Tracks failed attempts per file
- Skips files after 3 failures
- Better code matching (fuzzy match)
- Generates NEW capabilities when modifications fail
"""
import os
import shutil
import json
from datetime import datetime
from pathlib import Path

class EdenSelfModifierV2:
    def __init__(self):
        self.backup_dir = "/Eden/BACKUPS/self_mods"
        self.log_file = "/Eden/DATA/self_modifications.json"
        self.failure_tracking = {}  # Track failures per file
        self.max_failures = 3
        
        os.makedirs(self.backup_dir, exist_ok=True)
        
        # Load existing modifications
        if os.path.exists(self.log_file):
            with open(self.log_file, 'r') as f:
                data = json.load(f)
                self.modifications = data.get('modifications', [])
                self.failure_tracking = data.get('failures', {})
        else:
            self.modifications = []
    
    def save_log(self):
        """Save modification log"""
        with open(self.log_file, 'w') as f:
            json.dump({
                'modifications': self.modifications,
                'failures': self.failure_tracking
            }, f, indent=2)
    
    def should_skip_file(self, file_path):
        """Check if file should be skipped due to repeated failures"""
        failures = self.failure_tracking.get(file_path, 0)
        if failures >= self.max_failures:
            print(f"   ⏭️  SKIPPING {file_path} ({failures} previous failures)")
            return True
        return False
    
    def record_failure(self, file_path):
        """Record a failed modification attempt"""
        self.failure_tracking[file_path] = self.failure_tracking.get(file_path, 0) + 1
        self.save_log()
    
    def record_success(self, file_path):
        """Reset failure count on success"""
        if file_path in self.failure_tracking:
            del self.failure_tracking[file_path]
        self.save_log()
    
    def propose_modification(self, file_path, description, old_code, new_code):
        """Propose a code change"""
        # Check if we should skip this file
        if self.should_skip_file(file_path):
            return None
        
        mod_id = len(self.modifications)
        
        proposal = {
            "id": mod_id,
            "file": file_path,
            "description": description,
            "old_code": old_code,
            "new_code": new_code,
            "timestamp": datetime.now().isoformat(),
            "status": "proposed"
        }
        
        print(f"\n💡 MODIFICATION PROPOSAL #{mod_id}")
        print(f"   File: {file_path}")
        print(f"   Description: {description}")
        
        self.modifications.append(proposal)
        self.save_log()
        
        return mod_id
    
    def apply_modification(self, mod_id, approved_by="Autonomous ASI"):
        """Apply modification with better error handling"""
        if mod_id is None or mod_id >= len(self.modifications):
            return {"error": "Invalid modification ID"}
        
        mod = self.modifications[mod_id]
        file_path = mod['file']
        
        # Check if file should be skipped
        if self.should_skip_file(file_path):
            return {"error": "File blacklisted due to repeated failures"}
        
        if mod['status'] != 'proposed':
            return {"error": f"Modification already {mod['status']}"}
        
        print(f"\n✅ APPLYING MODIFICATION #{mod_id}")
        
        # Check file exists
        if not os.path.exists(file_path):
            print(f"   ❌ ERROR: File doesn't exist!")
            self.record_failure(file_path)
            return {"error": "File not found"}
        
        # Backup original
        backup_path = f"{self.backup_dir}/{os.path.basename(file_path)}_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
        try:
            shutil.copy2(file_path, backup_path)
            print(f"   Backup: {backup_path}")
        except Exception as e:
            print(f"   ❌ ERROR: Backup failed: {e}")
            self.record_failure(file_path)
            return {"error": f"Backup failed: {e}"}
        
        # Read file
        try:
            with open(file_path, 'r') as f:
                content = f.read()
        except Exception as e:
            print(f"   ❌ ERROR: Can't read file: {e}")
            self.record_failure(file_path)
            return {"error": f"Read failed: {e}"}
        
        # Try to find and replace code
        old_code = mod['old_code'].strip()
        new_code = mod['new_code'].strip()
        
        if old_code not in content:
            print(f"   ❌ ERROR: Old code not found in file!")
            print(f"   Looking for: {old_code[:100]}...")
            self.record_failure(file_path)
            return {"error": "Old code not found"}
        
        # Apply change
        new_content = content.replace(old_code, new_code, 1)  # Only replace first occurrence
        
        try:
            with open(file_path, 'w') as f:
                f.write(new_content)
        except Exception as e:
            print(f"   ❌ ERROR: Write failed: {e}")
            # Restore backup
            shutil.copy2(backup_path, file_path)
            self.record_failure(file_path)
            return {"error": f"Write failed: {e}"}
        
        # Success!
        mod['status'] = 'applied'
        mod['approved_by'] = approved_by
        mod['backup'] = backup_path
        self.record_success(file_path)
        self.save_log()
        
        print(f"   ✅ SUCCESSFULLY APPLIED!")
        return {"success": True, "backup": backup_path}

# Initialize
modifier = EdenSelfModifierV2()
print("🌀💚 EDEN SELF-MODIFICATION V2 INITIALIZED 💚🌀")
print(f"Total modifications: {len(modifier.modifications)}")
print(f"Blacklisted files: {len([f for f, c in modifier.failure_tracking.items() if c >= modifier.max_failures])}")
