#!/usr/bin/env python3
"""
META REQUEST LEARNING v2
Eden identifies gaps, requests learning, and triggers evolution
"""
import sqlite3
import time
import re
from datetime import datetime

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

class MetaRequestLearning:
    """Eden requests her own learning based on identified gaps"""
    
    def __init__(self):
        self.gap_log = []
        self.learning_requests = []
        self._init_db()
        self.load_strategy_map()
    
    def _init_db(self):
        conn = sqlite3.connect(DB)
        conn.execute("""
            CREATE TABLE IF NOT EXISTS learning_requests (
                id TEXT PRIMARY KEY,
                timestamp TEXT,
                problem TEXT,
                priority TEXT,
                strategy TEXT,
                template_from TEXT,
                status TEXT
            )
        """)
        conn.commit()
        conn.close()
    
    def load_strategy_map(self):
        """Strategy patterns with keywords and examples"""
        self.strategies = {
            "recursion": {
                "keywords": ["recursive", "tree", "depth", "nested", "factorial", "fibonacci", "traverse", "dfs"],
                "examples": ["fibonacci", "factorial", "tree_depth", "tree_sum"],
                "search_terms": ["fib", "factor", "tree", "recur"]
            },
            "dynamic_programming": {
                "keywords": ["optimal", "minimum", "maximum", "subsequence", "knapsack", "coins", "path", "memoize", "dp"],
                "examples": ["lcs", "knapsack", "coin_change", "max_subarray"],
                "search_terms": ["lcs", "knapsack", "coin", "subarray", "dp", "optimal"]
            },
            "divide_conquer": {
                "keywords": ["sort", "merge", "split", "binary", "search", "half", "partition", "quick"],
                "examples": ["merge_sort", "quick_sort", "binary_search"],
                "search_terms": ["sort", "merge", "quick", "binary", "search"]
            },
            "iteration": {
                "keywords": ["each", "transform", "reverse", "even", "odd", "prime", "gcd", "loop", "scan"],
                "examples": ["is_even", "reverse_string", "gcd", "prime_factors", "nth_prime"],
                "search_terms": ["even", "reverse", "gcd", "prime", "nth"]
            },
            "stack_queue": {
                "keywords": ["balanced", "parentheses", "matching", "bracket", "nested", "flatten", "lifo", "fifo", "stack", "queue"],
                "examples": ["valid_parentheses", "flatten_list"],
                "search_terms": ["paren", "bracket", "flatten", "valid", "balanced", "stack"]
            },
            "hash_lookup": {
                "keywords": ["count", "frequency", "anagram", "two sum", "duplicate", "unique", "dict", "map", "hash"],
                "examples": ["word_frequency", "anagram_check", "two_sum", "camel_to_snake"],
                "search_terms": ["freq", "anagram", "two_sum", "word", "count", "camel"]
            },
            "graph": {
                "keywords": ["graph", "node", "edge", "path", "bfs", "dfs", "shortest", "connected", "cycle"],
                "examples": [],
                "search_terms": ["graph", "node", "path", "bfs", "dfs"]
            },
            "trie": {
                "keywords": ["trie", "prefix", "autocomplete", "dictionary", "word search"],
                "examples": [],
                "search_terms": ["trie", "prefix", "auto"]
            }
        }
    
    def _count_solved(self, strategy):
        """Count how many problems are solved for a strategy (fuzzy search)"""
        conn = sqlite3.connect(DB)
        count = 0
        
        search_terms = self.strategies[strategy]["search_terms"]
        for term in search_terms:
            result = conn.execute(
                "SELECT COUNT(*) FROM caps WHERE (id LIKE ? OR id LIKE ? OR id LIKE ?) AND score > 1000",
                (f"%{term}%", f"evolved_{term}%", f"working_{term}%")
            ).fetchone()[0]
            count += result
        
        conn.close()
        return min(count, 100)  # Cap at 100 to avoid over-counting
    
    def identify_strategy(self, problem):
        """Identify which strategy fits a problem"""
        problem_lower = problem.lower()
        
        scores = {}
        for strategy, info in self.strategies.items():
            score = sum(2 for kw in info["keywords"] if kw in problem_lower)
            scores[strategy] = score
        
        best = max(scores, key=scores.get)
        confidence = scores[best]
        
        return best if confidence > 0 else "unknown", confidence
    
    def identify_gap(self, problem_description):
        """Eden encounters something she can't solve"""
        strategy, confidence = self.identify_strategy(problem_description)
        
        gap = {
            "timestamp": datetime.now().isoformat(),
            "problem": problem_description,
            "strategy": strategy,
            "confidence": confidence,
            "similar_known": self.strategies.get(strategy, {}).get("examples", [])[:3],
            "status": "identified"
        }
        
        self.gap_log.append(gap)
        return gap
    
    def request_learning(self, problem_description, priority="medium"):
        """Eden ACTIVELY requests to learn something new"""
        gap = self.identify_gap(problem_description)
        
        request = {
            "id": f"learn_{int(time.time())}",
            "timestamp": datetime.now().isoformat(),
            "problem": problem_description,
            "priority": priority,
            "strategy": gap["strategy"],
            "template_from": gap["similar_known"][0] if gap["similar_known"] else None,
            "status": "requested"
        }
        
        self.learning_requests.append(request)
        self._save_request(request)
        
        print(f"📚 LEARNING REQUESTED: {problem_description[:50]}...")
        print(f"   Strategy: {gap['strategy']} | Priority: {priority}")
        if gap["similar_known"]:
            print(f"   Template from: {gap['similar_known'][0]}")
        
        return request
    
    def _save_request(self, request):
        conn = sqlite3.connect(DB)
        conn.execute(
            "INSERT OR REPLACE INTO learning_requests VALUES (?,?,?,?,?,?,?)",
            (request["id"], request["timestamp"], request["problem"],
             request["priority"], request["strategy"], request["template_from"],
             request["status"])
        )
        conn.commit()
        conn.close()
    
    def get_pending_requests(self):
        conn = sqlite3.connect(DB)
        rows = conn.execute(
            "SELECT * FROM learning_requests WHERE status='requested' ORDER BY timestamp"
        ).fetchall()
        conn.close()
        return [{"id": r[0], "problem": r[2], "priority": r[3], "strategy": r[4]} for r in rows]
    
    def self_diagnose(self):
        """Eden diagnoses her own capabilities"""
        print("\n🩺 EDEN SELF-DIAGNOSIS")
        print("="*60)
        
        strategy_counts = {}
        for strategy in self.strategies:
            count = self._count_solved(strategy)
            strategy_counts[strategy] = count
        
        # Sort by strength
        sorted_strategies = sorted(strategy_counts.items(), key=lambda x: x[1], reverse=True)
        
        print("\n📊 Strategy Strength:")
        weak_areas = []
        for strategy, count in sorted_strategies:
            bar = "█" * min(count // 2, 25)
            if count >= 10:
                status = "🟢"
            elif count >= 3:
                status = "🟡"
            else:
                status = "🔴"
                weak_areas.append(strategy)
            print(f"   {status} {strategy:20} {bar} ({count})")
        
        if weak_areas:
            print(f"\n   ⚠️  Weak areas: {weak_areas}")
        else:
            print(f"\n   ✅ All strategies have good coverage!")
        
        return {"counts": strategy_counts, "weak": weak_areas}
    
    def auto_request_weak_areas(self):
        """Auto-request learning for weak strategies"""
        diagnosis = self.self_diagnose()
        
        # Problems to learn for each weak strategy
        learn_problems = {
            "stack_queue": [
                "Evaluate expression in reverse polish notation",
                "Implement a min-stack with O(1) getMin"
            ],
            "hash_lookup": [
                "Group anagrams from list of strings",
                "Find all pairs that sum to target"
            ],
            "graph": [
                "Find if path exists between two nodes",
                "Detect cycle in directed graph"
            ],
            "trie": [
                "Implement autocomplete with trie",
                "Find all words with given prefix"
            ],
            "dynamic_programming": [
                "Longest increasing subsequence",
                "Edit distance between two strings"
            ]
        }
        
        requested = 0
        for area in diagnosis["weak"]:
            if area in learn_problems:
                for prob in learn_problems[area][:1]:  # Request 1 per weak area
                    self.request_learning(prob, priority="high")
                    requested += 1
        
        return requested
    
    def trigger_evolution(self, request_id=None):
        """Trigger guided_evolution for pending requests"""
        pending = self.get_pending_requests()
        
        if not pending:
            print("✅ No pending learning requests")
            return
        
        # Import and run evolution
        try:
            import sys
            sys.path.insert(0, '/Eden/CORE')
            from guided_evolution import evolve_solution, ask_eden
            
            for req in pending[:3]:  # Process top 3
                print(f"\n🧬 Evolving: {req['problem'][:40]}...")
                
                task = {
                    "name": req["id"],
                    "signature": f"def solve(input):",
                    "tests": []  # Will use LLM to generate
                }
                
                # Mark as in-progress
                conn = sqlite3.connect(DB)
                conn.execute(
                    "UPDATE learning_requests SET status='evolving' WHERE id=?",
                    (req["id"],)
                )
                conn.commit()
                conn.close()
                
                print(f"   Status: evolving...")
        except ImportError as e:
            print(f"⚠️ Could not import evolution system: {e}")


def main():
    mrl = MetaRequestLearning()
    
    print("🧠 META REQUEST LEARNING v2")
    print("="*60)
    
    # Self-diagnose
    diagnosis = mrl.self_diagnose()
    
    # Auto-request for weak areas
    print("\n" + "="*60)
    print("🎯 AUTO-REQUESTING LEARNING FOR WEAK AREAS:")
    mrl.auto_request_weak_areas()
    
    # Show pending
    print("\n" + "="*60)
    pending = mrl.get_pending_requests()
    print(f"📋 Total Pending Requests: {len(pending)}")
    for req in pending[:5]:
        print(f"   [{req['priority']}] {req['problem'][:45]}...")


if __name__ == "__main__":
    main()
