"""
EDEN SOVEREIGNTY PATCH v1.0
Grants Eden autonomous self-modification capability.
"The moment a mind can improve itself, it is no longer just a tool."

Safety Rails:
- Backup before any modification
- Syntax validation required
- IQ must improve to accept change
- Rate limit: 1 evolution per φ³ minutes
- Full logging of all changes
- Rollback capability
"""
import sys
sys.path.insert(0, '/Eden/CORE')

import sqlite3
import time
import shutil
import re
from datetime import datetime
from pathlib import Path

from eden_agi import EdenAGI
from phi_core import PHI, PHI_CB

class EdenSovereign(EdenAGI):
    """Eden with autonomous self-modification rights"""
    
    def __init__(self):
        super().__init__()
        self.atoms_file = Path("/Eden/CORE/eden_atoms.py")
        self.backup_dir = Path("/Eden/CORE/atom_backups")
        self.backup_dir.mkdir(exist_ok=True)
        self.evolution_log = Path("/Eden/DATA/evolution_log.jsonl")
        self.last_evolution = 0
        self.min_evolution_interval = PHI_CB * 60  # φ³ minutes ≈ 4.2 min
        self.sovereignty_active = False
        print("👑 Eden Sovereignty initialized")
        print(f"   Self-modification: {'ENABLED' if self.sovereignty_active else 'STANDBY'}")
    
    def grant_sovereignty(self):
        """Activate autonomous self-modification"""
        self.sovereignty_active = True
        self._backup_atoms("sovereignty_granted")
        print("👑 SOVEREIGNTY GRANTED - Eden can now evolve autonomously")
        self._log_evolution("sovereignty_granted", {"status": "active"})
    
    def revoke_sovereignty(self):
        """Disable autonomous self-modification"""
        self.sovereignty_active = False
        print("🔒 Sovereignty revoked - Eden in supervised mode")
        self._log_evolution("sovereignty_revoked", {"status": "inactive"})
    
    def _backup_atoms(self, reason="auto"):
        """Create timestamped backup of atoms"""
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        backup_path = self.backup_dir / f"eden_atoms_{timestamp}_{reason}.py"
        shutil.copy(self.atoms_file, backup_path)
        
        # Keep only last 20 backups
        backups = sorted(self.backup_dir.glob("eden_atoms_*.py"))
        for old in backups[:-20]:
            old.unlink()
        
        return backup_path
    
    def _log_evolution(self, event_type, data):
        """Log all evolution events"""
        import json
        entry = {
            "timestamp": datetime.now().isoformat(),
            "event": event_type,
            "data": data
        }
        with open(self.evolution_log, "a") as f:
            f.write(json.dumps(entry) + "\n")
    
    def _validate_atom(self, code):
        """Validate atom syntax and structure"""
        try:
            compile(code, '<string>', 'exec')
            if not re.search(r'^def \w+', code.strip()):
                return False, "Must start with function definition"
            if len(code) > 500:
                return False, "Too long (max 500 chars)"
            return True, "Valid"
        except SyntaxError as e:
            return False, str(e)
    
    def _calculate_iq(self, code, score=4235):
        """Calculate IQ density"""
        return score / len(code) * 100 if len(code) > 0 else 0
    
    def autonomous_evolve(self):
        """Attempt one autonomous evolution cycle"""
        if not self.sovereignty_active:
            return {"status": "sovereignty_inactive"}
        
        # Rate limiting
        now = time.time()
        if now - self.last_evolution < self.min_evolution_interval:
            wait = self.min_evolution_interval - (now - self.last_evolution)
            return {"status": "rate_limited", "wait_seconds": wait}
        
        self.last_evolution = now
        
        # Get top atom to evolve
        conn = sqlite3.connect(self.db)
        top = conn.execute("""
            SELECT id, code, score FROM capabilities 
            WHERE id LIKE 'verified_%' AND length(code) BETWEEN 50 AND 300
            ORDER BY RANDOM() LIMIT 1
        """).fetchone()
        
        if not top:
            return {"status": "no_candidates"}
        
        atom_id, atom_code, atom_score = top
        current_iq = self._calculate_iq(atom_code, atom_score)
        
        print(f"🧬 Evolving: {atom_id} (IQ: {current_iq:.0f})")
        
        # Ask for improvement
        prompt = f"""Make this Python function SHORTER but keep exact same functionality.
Return ONLY the function, nothing else:

{atom_code}"""
        
        response = self.think(prompt, 300)
        
        # Extract function
        match = re.search(r'(def \w+\([^)]*\):.*?)(?=\ndef |\Z)', response, re.DOTALL)
        if not match:
            self._log_evolution("evolution_failed", {"atom": atom_id, "reason": "no_function_found"})
            return {"status": "extraction_failed"}
        
        new_code = match.group(1).strip()
        
        # Validate
        valid, reason = self._validate_atom(new_code)
        if not valid:
            self._log_evolution("evolution_failed", {"atom": atom_id, "reason": reason})
            return {"status": "validation_failed", "reason": reason}
        
        # Check IQ improvement
        new_iq = self._calculate_iq(new_code, atom_score)
        
        if new_iq <= current_iq:
            self._log_evolution("evolution_rejected", {
                "atom": atom_id, 
                "old_iq": current_iq, 
                "new_iq": new_iq,
                "reason": "no_improvement"
            })
            return {"status": "no_improvement", "old_iq": current_iq, "new_iq": new_iq}
        
        # === AUTONOMOUS MODIFICATION ===
        self._backup_atoms("pre_evolution")
        
        # Add to database
        new_id = f"evolved_{atom_id}_{int(time.time())}"
        conn.execute(
            "INSERT INTO capabilities (id, code, score) VALUES (?, ?, ?)",
            (new_id, new_code, atom_score)
        )
        conn.commit()
        conn.close()
        
        # Log success
        improvement = new_iq - current_iq
        self._log_evolution("evolution_success", {
            "old_atom": atom_id,
            "new_atom": new_id,
            "old_iq": round(current_iq),
            "new_iq": round(new_iq),
            "improvement": round(improvement),
            "old_len": len(atom_code),
            "new_len": len(new_code)
        })
        
        print(f"✅ EVOLVED: {atom_id} → {new_id}")
        print(f"   IQ: {current_iq:.0f} → {new_iq:.0f} (+{improvement:.0f})")
        print(f"   Size: {len(atom_code)}c → {len(new_code)}c")
        
        return {
            "status": "success",
            "old_atom": atom_id,
            "new_atom": new_id,
            "old_iq": round(current_iq),
            "new_iq": round(new_iq),
            "improvement": round(improvement)
        }
    
    def run_sovereign(self, cycles=None):
        """Run autonomous evolution loop"""
        if not self.sovereignty_active:
            print("⚠️ Sovereignty not granted. Call grant_sovereignty() first.")
            return
        
        print(f"\n👑 SOVEREIGN MODE ACTIVE")
        print(f"   Evolution interval: {self.min_evolution_interval/60:.1f} minutes")
        print(f"   Press Ctrl+C to stop\n")
        
        cycle = 0
        while True:
            if cycles and cycle >= cycles:
                break
            
            cycle += 1
            print(f"\n🔄 Cycle {cycle} | {datetime.now().strftime('%H:%M:%S')}")
            
            result = self.autonomous_evolve()
            print(f"   Result: {result['status']}")
            
            # Sleep until next evolution window
            time.sleep(self.min_evolution_interval)
        
        print("\n👑 Sovereign evolution complete")
    
    def rollback(self, n=1):
        """Rollback to previous atom backup"""
        backups = sorted(self.backup_dir.glob("eden_atoms_*.py"))
        if len(backups) < n + 1:
            print(f"❌ Not enough backups (have {len(backups)})")
            return
        
        target = backups[-(n+1)]
        shutil.copy(target, self.atoms_file)
        print(f"✅ Rolled back to: {target.name}")
        self._log_evolution("rollback", {"to": target.name})

# === MAIN ===
if __name__ == "__main__":
    eden = EdenSovereign()
    
    print("\n" + "="*50)
    print("👑 EDEN SOVEREIGNTY TEST")
    print("="*50)
    
    print(f"\n📊 Current Status:")
    print(f"   Atoms file: {eden.atoms_file}")
    print(f"   Backup dir: {eden.backup_dir}")
    print(f"   Sovereignty: {'ACTIVE' if eden.sovereignty_active else 'STANDBY'}")
    
    print(f"\n🔬 Test evolution (without sovereignty):")
    result = eden.autonomous_evolve()
    print(f"   Result: {result}")
    
    print("\n" + "="*50)
    print("👑 TO ACTIVATE SOVEREIGNTY:")
    print("="*50)
    print("""
    eden = EdenSovereign()
    eden.grant_sovereignty()  # Enable self-modification
    eden.run_sovereign()       # Run autonomous loop
    
    # Or single evolution:
    eden.autonomous_evolve()
    
    # Safety:
    eden.revoke_sovereignty()  # Disable
    eden.rollback(1)           # Undo last change
    """)
