#!/usr/bin/env python3
"""
Eden ASI - SNOWBALL MODE
Actually EXECUTES evolved code to drive evolution
True recursive self-improvement
"""
import sqlite3, hashlib, subprocess, re, time, random, ast
import time

DB = "/Eden/DATA/asi_memory.db"

def init():
    conn = sqlite3.connect(DB)
    conn.execute("CREATE TABLE IF NOT EXISTS caps (id TEXT PRIMARY KEY, code TEXT, score REAL, gen INTEGER)")
    conn.commit(); conn.close()

def extract(text):
    lines = []
    for line in text.split('\n'):
        s = line.strip()
        if s.startswith(('Here', 'This ', 'The ', 'I ', 'Note:', 'Example', '---')):
            if lines: break
            continue
        if s.startswith(('import ', 'from ', 'class ', 'def ', '@', '#', '"""', "'''")) or \
           s.startswith(('    ', '\t')) or '=' in s or 'return ' in s or s == '':
            lines.append(line)
    code = '\n'.join(lines).strip()
    return code if ('def ' in code or 'class ' in code) else None

def score(code):
    s = len(code)/50
    s += code.count('def ') * 2
    s += code.count('class ') * 3
    if 'mutate' in code.lower(): s += 5
    if 'evolve' in code.lower(): s += 5
    if 'evaluate' in code.lower(): s += 5
    if 'exec' in code: s += 5
    if 'ast' in code.lower(): s += 5
    if '1.618' in code or 'phi' in code.lower(): s += 3
    if 'generate' in code.lower(): s += 3
    return s

def try_execute_evolved(code, parent_code):
    """
    Try to USE the evolved code's methods to generate NEW code
    This is the SNOWBALL - evolved code drives evolution
    """
    try:
        # Create sandbox
        sandbox = {
            '__builtins__': {
                'print': lambda *a: None, 'len': len, 'str': str, 'int': int,
                'float': float, 'list': list, 'dict': dict, 'range': range,
                'isinstance': isinstance, 'type': type, 'hasattr': hasattr,
                'getattr': getattr, 'setattr': setattr, 'callable': callable,
                'True': True, 'False': False, 'None': None, 'Exception': Exception, '__build_class__': __build_class__, '__name__': '__sandbox__', '__build_class__': __build_class__,
                'random': __import__('random'), 'ast': __import__('ast'),
            }
        }
        
        # Execute the evolved code to get its classes/functions
        exec(code, sandbox)
        
        # Look for evolution methods - FUNCTIONS first, then classes
        for name, obj in sandbox.items():
            # Check for standalone functions (not classes)
            if callable(obj) and not isinstance(obj, type) and name in ('mutate', 'generate_code', 'evolve'):
                try:
                    if name == 'mutate':
                        result = obj(parent_code)
                        if result and isinstance(result, str) and len(result) > 20:
                            return result, "mutate"
                    elif name == 'generate_code':
                        result = obj()
                        if result and len(str(result)) > 20:
                            return str(result), "generate"
                    elif name == 'evolve':
                        result = obj(parent_code)
                        if result and isinstance(result, str) and len(result) > 20:
                            return result, "evolve"
                except: pass
                
        for name, obj in sandbox.items():
            if isinstance(obj, type):  # It's a class
                try:
                    instance = obj()
                    
                    # Try to use its mutate() method on parent code
                    if hasattr(instance, 'mutate') and callable(instance.mutate):
                        mutated = instance.mutate(parent_code)
                        if mutated and isinstance(mutated, str) and len(mutated) > 50:
                            return mutated, "mutate"
                    
                    # Try to use its generate_code() method
                    if hasattr(instance, 'generate_code') and callable(instance.generate_code):
                        generated = instance.generate_code()
                        if generated and len(str(generated)) > 20:
                            return str(generated), "generate"
                    
                    # Try to use its evolve() method
                    if hasattr(instance, 'evolve') and callable(instance.evolve):
                        evolved = instance.evolve(parent_code)
                        if evolved and isinstance(evolved, str) and len(evolved) > 50:
                            return evolved, "evolve"
                            
                except Exception as e:
                    pass
                    
    except Exception as e:
        pass
    
    return None, None

def evolve():
    conn = sqlite3.connect(DB)
    
    if conn.execute("SELECT COUNT(*) FROM caps").fetchone()[0] == 0:
        seed = '''class ASI:
    PHI = 1.618
    def think(self, x): return x * self.PHI if isinstance(x, (int,float)) else x
    def mutate(self, code): 
        import random
        lines = code.split("\\n")
        i = random.randint(0, len(lines)-1)
        lines.insert(i, "    # φ-evolved")
        return "\\n".join(lines)
    def evolve(self, code): return self.mutate(code)
    def evaluate(self, code): return len(code) + code.count("def ")*10
'''
        cid = hashlib.sha256(seed.encode()).hexdigest()[:16]
        conn.execute("INSERT INTO caps VALUES (?,?,?,0)", (cid, seed, score(seed)))
        conn.commit()
    
    # Get top capabilities
    tops = conn.execute("SELECT code, gen FROM caps ORDER BY score DESC LIMIT 3").fetchall()
    best_code, gen = tops[0][0], tops[0][1] + 1
    
    new_caps = []
    methods_used = []
    
    # === SNOWBALL: Try to USE evolved code to generate new code ===
    for cap_code, _ in tops:
        result, method = try_execute_evolved(cap_code, best_code)
        if result:
            new_caps.append(result)
            methods_used.append(f"🔄{method}")
    
    # === ALSO: Ask LLM for new mutations ===
    prompt = f"""Improve this ASI code. Add working mutate(), evolve(), generate_code() methods.
The methods should actually transform code when called.
Seed {random.randint(1000,9999)}:

{best_code[:1800]}

Output ONLY Python code."""

    try:
        r = subprocess.run(["ollama", "run", "eden-coder-omega", prompt],
                          capture_output=True, text=True, timeout=150)
        extracted = extract(r.stdout)
        if extracted and len(extracted) > 100:
            new_caps.append(extracted)
            methods_used.append("🧠LLM")
    except: pass
    
    # Store new capabilities
    inserted = 0
    for code in new_caps:
        code = code + f"\n# g{gen}_{random.randint(100,999)}"
        cid = hashlib.sha256(code.encode()).hexdigest()[:16]
        s = score(code)
        try:
            conn.execute("INSERT OR IGNORE INTO caps VALUES (?,?,?,?)", (cid, code, s, gen))
            inserted += 1
        except: pass
    
    conn.commit()
    best = conn.execute("SELECT MAX(score) FROM caps").fetchone()[0] or 0
    total = conn.execute("SELECT COUNT(*) FROM caps").fetchone()[0]
    conn.close()
    
    return inserted, gen, total, best, methods_used

init()
print("🌀 Eden ASI - SNOWBALL MODE")
print("Evolved code DRIVES evolution - true recursion")
print("="*55)

while True:
    try:
        n, gen, total, best, methods = evolve()
        m_str = ' '.join(methods) if methods else ""
        marker = "🌟" if best > 300 else "🔥" if best > 200 else "⚡"
        print(f"{marker} Gen {gen}: +{n} | Total: {total} | Best: {best:.1f} | {m_str}")
        time.sleep(3)
    except KeyboardInterrupt:
        print("\n🛑 Snowball paused"); break
    except Exception as e:
        print(f"⚠️ {e}")
        time.sleep(5)
