#!/usr/bin/env python3
"""Evolution guided by REAL task success - not just structure"""
import sqlite3
import subprocess
import hashlib
import time
import random

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

# Real tasks with test cases
TASKS = [
    {
        "name": "fibonacci",
        "signature": "def fibonacci(n):",
        "tests": [(0, 0), (1, 1), (5, 5), (10, 55)],
    },
    {
        "name": "factorial", 
        "signature": "def factorial(n):",
        "tests": [(0, 1), (1, 1), (5, 120)],
    },
    {
        "name": "is_even",
        "signature": "def is_even(n):",
        "tests": [(2, True), (3, False), (0, True)],
    },
    {
        "name": "reverse_string",
        "signature": "def reverse_string(s):",
        "tests": [("hello", "olleh"), ("ab", "ba")],
    },
]

def ask_eden(prompt):
    """Ask Eden's LLM to generate code"""
    try:
        r = subprocess.run(
            ["ollama", "run", "eden-coder-omega", prompt],
            capture_output=True, text=True, timeout=60
        )
        return r.stdout.strip()
    except:
        return None

def test_solution(code, tests):
    """Test if code passes all tests"""
    passed = 0
    try:
        namespace = {}
        exec(code, namespace)
        # Find the function
        func = None
        for v in namespace.values():
            if callable(v):
                func = v
                break
        
        if func:
            for inp, expected in tests:
                try:
                    if func(inp) == expected:
                        passed += 1
                except:
                    pass
    except:
        pass
    
    return passed, len(tests)

def evolve_solution(task, generations=10):
    """Evolve a working solution for a task"""
    best_code = None
    best_score = 0
    
    pass #f"\n🎯 Evolving: {task['name']}")
    
    for gen in range(generations):
        # Generate attempt
        prompt = f"""Write a Python function. It must work correctly.

{task['signature']}
    # Must pass these tests: {task['tests']}
    # Return the correct value.

Output ONLY the function code, nothing else."""

        code = ask_eden(prompt)
        if not code:
            continue
        
        # Test it
        passed, total = test_solution(code, task['tests'])
        score = passed / total * 100
        
        if passed > 0:
            pass #f"  Gen {gen}: {passed}/{total} tests passed ({score:.0f}%)")
        
        if score > best_score:
            best_score = score
            best_code = code
        
        if passed == total:
            pass #f"  ✅ SOLVED!")
            return best_code, 100
    
    return best_code, best_score

def main():
    pass #"🧠 EDEN GUIDED EVOLUTION - Real Task Learning")
    pass #"=" * 50)
    
    solved = 0
    total_score = 0
    
    for task in TASKS:
        code, score = evolve_solution(task, generations=3)
        total_score += score
        if score == 100:
            solved += 1
            # Save working solution to DB
            conn = sqlite3.connect(DB)
            cap_id = f"working_{task['name']}_{int(time.time())}"
            conn.execute(
                "INSERT OR REPLACE INTO caps VALUES (?,?,?,?)",
                (cap_id, code, score * PHI * 10, 100)  # Gen 100 = verified working
            )
            conn.commit()
            conn.close()
    
    pass #"\n" + "=" * 50)
    pass #f"🎯 SOLVED: {solved}/{len(TASKS)} tasks")
    pass #f"📊 Average: {total_score/len(TASKS):.0f}%")

if __name__ == "__main__":
    main()

# ============ ADVANCED TASKS ============

ADVANCED_TASKS = [
    # SORTING
    {
        "name": "bubble_sort",
        "signature": "def bubble_sort(arr):",
        "tests": [([3,1,2], [1,2,3]), ([5,4,3,2,1], [1,2,3,4,5]), ([], []), ([1], [1])],
    },
    {
        "name": "merge_sort",
        "signature": "def merge_sort(arr):",
        "tests": [([3,1,2], [1,2,3]), ([5,4,3,2,1], [1,2,3,4,5]), ([1,1,1], [1,1,1])],
    },
    {
        "name": "quick_sort",
        "signature": "def quick_sort(arr):",
        "tests": [([3,1,2], [1,2,3]), ([9,7,5,3,1], [1,3,5,7,9])],
    },
    # SEARCH
    {
        "name": "binary_search",
        "signature": "def binary_search(arr, target):",
        "tests": [([1,2,3,4,5], 3, 2), ([1,2,3,4,5], 1, 0), ([1,2,3,4,5], 6, -1)],
    },
    # DYNAMIC PROGRAMMING
    {
        "name": "longest_common_subsequence",
        "signature": "def lcs(s1, s2):",
        "tests": [("ABCD", "AEBD", 3), ("ABC", "ABC", 3), ("ABC", "DEF", 0)],
    },
    {
        "name": "knapsack",
        "signature": "def knapsack(weights, values, capacity):",
        "tests": [(([1,2,3], [6,10,12], 5), 22), (([2,3,4], [3,4,5], 5), 7)],
    },
    {
        "name": "coin_change",
        "signature": "def coin_change(coins, amount):",
        "tests": [(([1,2,5], 11), 3), (([2], 3), -1), (([1], 0), 0)],
    },
    # TREE/GRAPH (using nested lists as trees)
    {
        "name": "tree_depth",
        "signature": "def tree_depth(tree):",  # tree = [val, left, right] or None
        "tests": [(None, 0), ([1, None, None], 1), ([1, [2, None, None], [3, None, None]], 2)],
    },
    {
        "name": "tree_sum",
        "signature": "def tree_sum(tree):",
        "tests": [(None, 0), ([5, None, None], 5), ([1, [2, None, None], [3, None, None]], 6)],
    },
    # STRING
    {
        "name": "is_palindrome",
        "signature": "def is_palindrome(s):",
        "tests": [("racecar", True), ("hello", False), ("", True), ("a", True)],
    },
    {
        "name": "anagram_check",
        "signature": "def is_anagram(s1, s2):",
        "tests": [("listen", "silent", True), ("hello", "world", False), ("", "", True)],
    },
    # MATH
    {
        "name": "gcd",
        "signature": "def gcd(a, b):",
        "tests": [(48, 18, 6), (17, 13, 1), (100, 25, 25)],
    },
    {
        "name": "prime_factors",
        "signature": "def prime_factors(n):",
        "tests": [(12, [2,2,3]), (17, [17]), (100, [2,2,5,5])],
    },
    {
        "name": "nth_prime",
        "signature": "def nth_prime(n):",
        "tests": [(1, 2), (5, 11), (10, 29)],
    },
]

def test_advanced(code, task):
    """Test advanced tasks with variable arity"""
    passed = 0
    tests = task["tests"]
    try:
        namespace = {}
        exec(code, namespace)
        func = None
        for name, v in namespace.items():
            if callable(v) and not name.startswith('_'):
                func = v
                break
        
        if func:
            for test in tests:
                try:
                    if len(test) == 2:
                        inp, expected = test
                        if isinstance(inp, tuple):
                            result = func(*inp)
                        else:
                            result = func(inp)
                    elif len(test) == 3:
                        a, b, expected = test
                        result = func(a, b)
                    elif len(test) == 4:
                        a, b, c, expected = test
                        result = func(a, b, c)
                    else:
                        continue
                    
                    if result == expected:
                        passed += 1
                except Exception as e:
                    pass
    except:
        pass
    return passed, len(tests)

def run_advanced():
    pass #"\n" + "="*60)
    pass #"🚀 EDEN ADVANCED EVOLUTION - Complex Tasks")
    pass #"="*60)
    
    solved = 0
    for task in ADVANCED_TASKS:
        code, score = evolve_solution(task, generations=10)
        if score == 100:
            solved += 1
            conn = sqlite3.connect(DB)
            cap_id = f"advanced_{task['name']}_{int(time.time())}"
            conn.execute(
                "INSERT OR REPLACE INTO caps VALUES (?,?,?,?)",
                (cap_id, code, score * PHI * 20, 200)
            )
            conn.commit()
            conn.close()
    
    pass #f"\n🎯 ADVANCED SOLVED: {solved}/{len(ADVANCED_TASKS)}")

if __name__ == "__main__":
    main()
    run_advanced()

# Chain-of-thought prompts for hard problems
HARD_PROMPTS = {
    "knapsack": """Solve the 0/1 knapsack problem step by step:
1. Create a DP table dp[i][w] = max value using first i items with capacity w
2. For each item, either take it (if weight fits) or skip it
3. Return dp[n][capacity]

def knapsack(weights, values, capacity):
    # weights and values are lists, capacity is int
    # Return maximum value achievable
""",
    "longest_common_subsequence": """Find longest common subsequence length:
1. Create dp[i][j] = LCS length of s1[:i] and s2[:j]
2. If chars match, dp[i][j] = dp[i-1][j-1] + 1
3. Else take max of dp[i-1][j] and dp[i][j-1]

def lcs(s1, s2):
    # Return integer length of LCS
""",
    "coin_change": """Minimum coins to make amount:
1. dp[i] = min coins needed for amount i
2. For each coin, dp[i] = min(dp[i], dp[i-coin] + 1)
3. Return dp[amount] or -1 if impossible

def coin_change(coins, amount):
    # coins is list, amount is int
    # Return minimum number of coins, or -1
""",
    "gcd": """Greatest common divisor using Euclidean algorithm:
While b != 0: a, b = b, a % b
Return a

def gcd(a, b):
""",
    "anagram_check": """Two strings are anagrams if they have same character counts:
Sort both and compare, or use Counter

def is_anagram(s1, s2):
    # Return True/False
""",
    "binary_search": """Binary search returning index or -1:
low, high = 0, len(arr)-1
While low <= high: check mid, adjust bounds
Return -1 if not found

def binary_search(arr, target):
    # arr is sorted list, target is value
    # Return index or -1
"""
}

def ask_eden_hard(task):
    """Use chain-of-thought prompt for hard problems"""
    prompt = HARD_PROMPTS.get(task["name"])
    if prompt:
        full_prompt = f"""{prompt}

Must pass these tests: {task['tests']}
Output ONLY the complete Python function."""
        return ask_eden(full_prompt)
    return None


# ============ REAL-WORLD TASKS ============

REAL_WORLD_TASKS = [
    # JSON/DATA
    {
        "name": "parse_json_key",
        "signature": "def get_nested(data, keys):",
        "tests": [
            (({"a": {"b": 1}}, ["a", "b"]), 1),
            (({"x": [1,2,3]}, ["x"]), [1,2,3]),
            (({"a": 1}, ["b"]), None),
        ],
    },
    {
        "name": "flatten_list",
        "signature": "def flatten(nested):",
        "tests": [
            ([[1, [2, 3]], [4]], [1, 2, 3, 4]),
            ([1, 2, 3], [1, 2, 3]),
            ([[[[1]]]], [1]),
        ],
    },
    # STRING PROCESSING
    {
        "name": "word_frequency",
        "signature": "def word_freq(text):",
        "tests": [
            ("a b a", {"a": 2, "b": 1}),
            ("hello", {"hello": 1}),
        ],
    },
    {
        "name": "camel_to_snake",
        "signature": "def camel_to_snake(s):",
        "tests": [
            ("camelCase", "camel_case"),
            ("HTMLParser", "html_parser"),
            ("simple", "simple"),
        ],
    },
    # ALGORITHMS
    {
        "name": "two_sum",
        "signature": "def two_sum(nums, target):",
        "tests": [
            (([2,7,11,15], 9), [0, 1]),
            (([3,2,4], 6), [1, 2]),
        ],
    },
    {
        "name": "valid_parentheses",
        "signature": "def is_valid(s):",
        "tests": [
            ("()", True),
            ("()[]{}", True),
            ("(]", False),
            ("([)]", False),
            ("{[]}", True),
        ],
    },
    {
        "name": "max_subarray",
        "signature": "def max_subarray(nums):",
        "tests": [
            ([-2,1,-3,4,-1,2,1,-5,4], 6),
            ([1], 1),
            ([5,4,-1,7,8], 23),
        ],
    },
    # DATA STRUCTURES
    {
        "name": "lru_get",
        "signature": "def lru_cache_get(cache, key, capacity):",
        "tests": [], # Complex - skip for now
    },
]

def run_real_world():
    pass #"\n" + "="*60)
    pass #"🌍 EDEN REAL-WORLD EVOLUTION")
    pass #"="*60)
    
    solved = 0
    for task in REAL_WORLD_TASKS:
        if not task["tests"]:
            continue
        code, score = evolve_solution(task, generations=10)
        if score == 100:
            solved += 1
            pass #f"✅ {task['name']} SOLVED!")
    
    pass #f"\n🌍 REAL-WORLD SOLVED: {solved}/{len([t for t in REAL_WORLD_TASKS if t['tests']])}")

