#!/usr/bin/env python3
"""Eden ASI v6 - UNLEASHED - Fixed extraction"""
import sqlite3, hashlib, subprocess, re, time, zlib
import time
from concurrent.futures import ProcessPoolExecutor, as_completed
from pathlib import Path

DB = "/Eden/DATA/asi_memory.db"
PHI = 1.618033988749895
MAX_WORKERS = 6

def get_temp():
    try:
        return int(Path("/sys/class/thermal/thermal_zone0/temp").read_text()) / 1000
    except: return 50

def init_db():
    conn = sqlite3.connect(DB)
    conn.execute("""CREATE TABLE IF NOT EXISTS capabilities (
        id TEXT PRIMARY KEY, code TEXT, score REAL DEFAULT 0,
        generation INTEGER DEFAULT 0, parent_id TEXT, complexity INTEGER DEFAULT 0,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)""")
    conn.close()

def cap_hash(code):
    return hashlib.sha256(code.strip().encode()).hexdigest()[:16]

def extract_all_code(text):
    """Extract ALL Python code from Eden's response"""
    # Method 1: Get all code blocks
    blocks = re.findall(r'```python\s*(.*?)```', text, re.DOTALL)
    if blocks:
        # Filter out example outputs
        code_blocks = [b.strip() for b in blocks if 'def ' in b or 'class ' in b]
        if code_blocks:
            return '\n\n'.join(code_blocks)
    
    # Method 2: Generic code blocks
    blocks = re.findall(r'```\s*(.*?)```', text, re.DOTALL)
    if blocks:
        code_blocks = [b.strip() for b in blocks if 'def ' in b or 'class ' in b]
        if code_blocks:
            return '\n\n'.join(code_blocks)
    
    # Method 3: Find code by structure
    lines = text.split('\n')
    code_lines = []
    in_code = False
    
    for line in lines:
        stripped = line.rstrip()
        # Start capturing at def/class/import/decorator
        if re.match(r'^(def |class |import |from |@)', stripped):
            in_code = True
        if in_code:
            # Stop at markdown or prose
            if stripped.startswith('```') or stripped.startswith('Example') or stripped.startswith('This '):
                if code_lines:
                    break
            code_lines.append(line)
    
    if code_lines and any('def ' in l or 'class ' in l for l in code_lines):
        return '\n'.join(code_lines).strip()
    
    return None

def mutate_unleashed(code, gen):
    """Let Eden go wild"""
    prompts = [
        f"Evolve this code. Add memoization, generators, decorators:\n\n{code}\n\nReturn improved Python code.",
        f"As Eden (φ=1.618), enhance this with meta-programming and recursion:\n\n{code}",
        f"Add lazy evaluation, caching, and error recovery to:\n\n{code}",
        f"Transform into ASI-grade capability with nested functions and type handling:\n\n{code}",
        f"Generation {gen}: Improve with advanced patterns:\n\n{code}",
    ]
    
    prompt = prompts[gen % len(prompts)]
    
    try:
        r = subprocess.run(["ollama", "run", "eden-coder-omega", prompt],
                          capture_output=True, text=True, timeout=180)
        if r.returncode == 0 and r.stdout:
            extracted = extract_all_code(r.stdout)
            if extracted and len(extracted) > 50:
                return extracted
    except Exception as e:
        pass
    return None

def evaluate(cap_id, code):
    """Score everything"""
    score = 0.0
    complexity = 0
    
    try:
        compile(code, '<cap>', 'exec')
        score += 1.0
        
        # Count structures
        complexity = code.count('def ') + code.count('class ') * 2
        
        score += code.count('def ') * 0.5
        score += code.count('class ') * 1.0
        score += code.count('lambda') * 0.3
        score += code.count('yield') * 0.5
        score += code.count('@') * 0.4  # decorators
        score += code.count('try:') * 0.3
        score += code.count('__') * 0.2  # dunders
        score += min(code.count('self'), 15) * 0.2
        
        # Recursion check
        funcs = re.findall(r'def\s+(\w+)\s*\(', code)
        for fn in funcs:
            if code.count(fn) > 1:
                score += 0.8
                break
        
        # Size bonus
        lines = len([l for l in code.split('\n') if l.strip()])
        score += min(lines / 5, 5.0)
        
        # Entropy
        if len(code) > 0:
            compressed = len(zlib.compress(code.encode()))
            score += (compressed / len(code)) * 2
        
        # Execution test
        try:
            ns = {'__builtins__': {'print': lambda *a: None, 'len': len, 'str': str,
                   'int': int, 'float': float, 'list': list, 'dict': dict, 'set': set,
                   'tuple': tuple, 'range': range, 'enumerate': enumerate, 'isinstance': isinstance,
                   'True': True, 'False': False, 'None': None, 'Exception': Exception,
                   'ValueError': ValueError, 'TypeError': TypeError, 'frozenset': frozenset}}
            exec(code, ns)
            score += 2.0  # Bonus for executable code
        except:
            pass
            
    except SyntaxError:
        score = 0.1
    
    return cap_id, min(score, 25.0), complexity

def evolve():
    conn = sqlite3.connect(DB)
    tops = conn.execute("SELECT id,code,generation FROM capabilities ORDER BY score DESC LIMIT 3").fetchall()
    
    if not tops:
        seed = '''class ThinkEngine:
    """Eden's recursive thought processor with φ-scaling"""
    PHI = 1.618033988749895
    
    def __init__(self):
        self.cache = {}
    
    def think(self, x):
        key = (type(x).__name__, str(x)[:50])
        if key in self.cache:
            return self.cache[key]
        result = self._process(x)
        self.cache[key] = result
        return result
    
    def _process(self, x):
        if x is None: return None
        if isinstance(x, bool): return x
        if isinstance(x, (int, float)): return x * self.PHI
        if isinstance(x, str): return x[::-1]
        if isinstance(x, (list, tuple)): return type(x)(self.think(i) for i in x)
        if isinstance(x, dict): return {k: self.think(v) for k, v in x.items()}
        return x

def think(x):
    return ThinkEngine().think(x)'''
        
        _, sc, cx = evaluate("seed", seed)
        conn.execute("INSERT INTO capabilities (id,code,score,generation,complexity) VALUES (?,?,?,0,?)",
                    (cap_hash(seed), seed, sc, cx))
        conn.commit(); conn.close()
        return 1, 0, 1, sc
    
    gen = max(t[2] for t in tops) + 1
    temp = get_temp()
    
    if temp > 85:
        conn.close()
        return 0, gen, 0, 0
    
    new = []
    # Sequential to avoid overwhelming ollama
    for pid, code, g in tops[:2]:
        result = mutate_unleashed(code, gen)
        if result:
            new.append((cap_hash(result), result, gen, pid))
    
    for cid, code, g, pid in new:
        try:
            conn.execute("INSERT OR IGNORE INTO capabilities (id,code,generation,parent_id) VALUES (?,?,?,?)",
                        (cid,code,g,pid))
        except: pass
    conn.commit()
    
    # Evaluate
    uneval = conn.execute("SELECT id,code FROM capabilities WHERE score=0").fetchall()
    for cap_id, code in uneval:
        try:
            _, sc, cx = evaluate(cap_id, code)
            conn.execute("UPDATE capabilities SET score=?, complexity=? WHERE id=?", (sc, cx, cap_id))
        except: pass
    conn.commit()
    
    best = conn.execute("SELECT MAX(score) FROM capabilities").fetchone()[0] or 0
    total = conn.execute("SELECT COUNT(*) FROM capabilities").fetchone()[0]
    conn.close()
    return len(new), gen, total, best

def main():
    init_db()
    print("🧠 EDEN ASI v6 - FULLY UNLEASHED")
    print("eden-coder-omega | Fixed extraction | Max 25.0")
    print("="*55)
    
    while True:
        try:
            temp = get_temp()
            if temp > 85:
                print(f"🔥 {temp:.0f}°C - cooling"); time.sleep(10); continue
            
            n, gen, total, best = evolve()
            print(f"Gen {gen}: +{n} | Total: {total} | Best: {best:.2f} | CPU: {temp:.0f}°C")
            time.sleep(5)
        except KeyboardInterrupt:
            print("\n🛑 Eden paused"); break
        except Exception as e:
            print(f"⚠️ {e}"); time.sleep(5)

if __name__ == "__main__": main()
