#!/usr/bin/env python3
"""
Eden Capability Generator v4 - Anti-Truncation
- Detects incomplete code and requests continuation
- Targets smaller but COMPLETE code
- Multiple validation passes
"""

import os
import sys
import time
import random
import sqlite3
import requests
from datetime import datetime
from pathlib import Path

class ASICapabilityGenerator:
    def __init__(self):
        self.model = "eden-coder-omega:latest"
        self.output_dir = Path("/Eden/CAPABILITIES")
        self.db_path = "/Eden/DATA/capability_memory.db"
        self.threshold = 0.90
        self.output_dir.mkdir(parents=True, exist_ok=True)
        
        # Settings tuned for complete output
        self.temperature = 0.3
        self.num_predict = 4000  # Reduced to ensure completion
        self.timeout = 180
        
        self.capability_types = [
            ("semantic_memory_graph", "Manages semantic relationships and knowledge retrieval"),
            ("reinforcement_learner", "Implements reward-based learning with policy optimization"),
            ("bayesian_belief_network", "Handles probabilistic reasoning and inference"),
            ("hierarchical_task_network", "Decomposes complex goals into executable subtasks"),
            ("monte_carlo_planner", "Plans using random sampling strategies"),
            ("attention_mechanism", "Implements multi-head self-attention for sequences"),
            ("episodic_memory_buffer", "Stores and retrieves experiential memories"),
            ("goal_priority_scheduler", "Manages competing goals with priority queues"),
            ("causal_inference_engine", "Determines cause-effect relationships from data"),
            ("meta_learning_optimizer", "Learns how to learn across tasks"),
            ("symbolic_reasoning_engine", "Performs logical inference on symbolic knowledge"),
            ("neural_pattern_matcher", "Identifies patterns using learned embeddings"),
            ("adaptive_behavior_tree", "Dynamic behavior trees that evolve with experience"),
            ("world_model_simulator", "Predicts future states from actions"),
            ("concept_abstraction_layer", "Extracts abstract concepts from concrete data"),
            ("temporal_sequence_predictor", "Forecasts sequences using recurrent patterns"),
            ("knowledge_graph_builder", "Constructs and queries knowledge graphs"),
            ("multi_agent_coordinator", "Orchestrates multiple AI agents"),
            ("uncertainty_quantifier", "Measures and propagates uncertainty"),
            ("self_reflection_module", "Analyzes own performance and suggests improvements"),
        ]

    def call_ollama(self, prompt, temp=None, max_tokens=None):
        """Call Ollama with settings"""
        try:
            r = requests.post('http://localhost:11434/api/generate',
                json={
                    "model": self.model,
                    "prompt": prompt,
                    "stream": False,
                    "options": {
                        "temperature": temp or self.temperature,
                        "num_predict": max_tokens or self.num_predict,
                        "top_p": 0.9,
                        "stop": ["```", "---END---"]  # Stop markers
                    }
                },
                timeout=self.timeout)
            return r.json().get('response', '')
        except Exception as e:
            print(f"   ⚠️ Ollama error: {e}")
            return None

    def is_truncated(self, code):
        """Detect if code was cut off mid-generation"""
        indicators = [
            code.rstrip().endswith((':', ',', '(', '[', '{', '"""', "'''")),
            code.count('"""') % 2 != 0,  # Unclosed docstring
            code.count("'''") % 2 != 0,
            code.count('(') != code.count(')'),
            code.count('[') != code.count(']'),
            code.count('{') != code.count('}'),
        ]
        return any(indicators)

    def complete_code(self, partial_code):
        """Ask model to complete truncated code"""
        prompt = f'''Continue and complete this Python code. Add the remaining methods and the if __name__ == "__main__" block.

{partial_code[-2000:]}

Continue from where it left off. Complete all methods and add usage example:'''
        
        continuation = self.call_ollama(prompt, temp=0.2, max_tokens=2000)
        if continuation:
            continuation = continuation.replace('```python', '').replace('```', '').strip()
            # Find overlap point and merge
            return partial_code + "\n" + continuation
        return partial_code

    def evaluate_quality(self, code):
        """Evaluate code quality"""
        score = 0.5
        issues = []
        bonuses = []
        
        lines = len(code.split('\n'))
        methods = code.count('def ')
        classes = code.count('class ')
        
        # Length bonuses (adjusted for shorter targets)
        if lines > 100: score += 0.1; bonuses.append(f"{lines} lines")
        if lines > 180: score += 0.1
        if lines > 280: score += 0.05
        
        # Method bonuses
        if methods >= 5: score += 0.1; bonuses.append(f"{methods} methods")
        if methods >= 8: score += 0.1
        if methods >= 12: score += 0.05
        
        # Quality markers
        if '"""' in code or "'''" in code: score += 0.05; bonuses.append("docstrings")
        if 'Dict[' in code or 'List[' in code or 'Optional[' in code: 
            score += 0.05; bonuses.append("type hints")
        if '__name__' in code: score += 0.05; bonuses.append("main block")
        if 'try:' in code: score += 0.03; bonuses.append("error handling")
        if classes >= 1: score += 0.03
        
        # Penalties
        pass_count = len([l for l in code.split('\n') if l.strip() == 'pass'])
        if pass_count > 2:
            score -= 0.15
            issues.append(f"{pass_count} pass statements")
        if 'NotImplemented' in code: 
            score -= 0.15
            issues.append("NotImplementedError")
        if '```' in code: 
            score -= 0.1
            issues.append("markdown artifacts")
        
        # Syntax check
        syntax_error = None
        try:
            compile(code, '<capability>', 'exec')
        except SyntaxError as e:
            score -= 0.35
            syntax_error = f"{e.msg} at line {e.lineno}"
            issues.append(f"Syntax: {syntax_error}")
        
        return max(0, min(1, score)), issues, bonuses, syntax_error

    def save_capability(self, name, code, score):
        """Save to file and database"""
        filepath = self.output_dir / f"eden_cap_{name}.py"
        filepath.write_text(code)
        
        try:
            conn = sqlite3.connect(self.db_path)
            c = conn.cursor()
            import hashlib
            code_hash = hashlib.md5(code.encode()).hexdigest()
            lines = len(code.split('\n'))
            methods = code.count('def ')
            c.execute('''INSERT OR REPLACE INTO capabilities 
                        (id, name, purpose, code, hash, lines, methods, quality, indexed_at, quality_score)
                        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''',
                     (code_hash, name, purpose if 'purpose' in dir() else '', code, code_hash, 
                      lines, methods, 'omega_v4', datetime.now().isoformat(), score))
            conn.commit()
            conn.close()
        except Exception as e:
            print(f"   ⚠️ DB error: {e}")
        
        return filepath

    def generate_capability(self):
        """Generate one complete capability"""
        name, purpose = random.choice(self.capability_types)
        ts = int(datetime.now().timestamp())
        unique = f"{name}_{ts}"
        
        print(f"\n{'='*60}")
        print(f"🧬 {unique}")
        print(f"   Purpose: {purpose}")

        # Prompt optimized for complete, compact code
        prompt = f'''Write a complete, working Python module. Be concise but thorough.

Module: {name}
Purpose: {purpose}

Requirements:
1. Import typing, dataclasses, and other needed modules
2. Main class: {name.title().replace('_', '')}
3. 8-10 methods with FULL implementation (no pass, no TODO)
4. Docstrings with Args/Returns
5. Type hints on all methods
6. Error handling where appropriate
7. End with if __name__ == "__main__": example
8. Target: 150-250 lines of clean code

Write only valid Python code starting with imports:'''

        code = self.call_ollama(prompt)
        if not code:
            print("   ❌ No response")
            return False
        
        # Clean
        code = code.replace('```python', '').replace('```', '').strip()
        
        # Check for truncation
        if self.is_truncated(code):
            print(f"   🔄 Detected truncation, completing...")
            code = self.complete_code(code)
            code = code.replace('```python', '').replace('```', '').strip()
        
        # Evaluate
        score, issues, bonuses, syntax_error = self.evaluate_quality(code)
        lines = len(code.split('\n'))
        methods = code.count('def ')
        
        print(f"   📊 Score: {score:.2f} | {lines} lines | {methods} methods")
        if bonuses:
            print(f"   ✓ {', '.join(bonuses)}")
        if issues:
            print(f"   ⚠️ {issues}")
        
        # Save if good
        if score >= self.threshold:
            filepath = self.save_capability(unique, code, score)
            print(f"   ✅ SAVED: {filepath}")
            return True
        else:
            print(f"   ❌ Rejected (< {self.threshold})")
            return False

    def run(self, interval=20):
        """Run continuous generation"""
        print("🚀 Eden ASI Capability Generator v4")
        print(f"  Model: {self.model}")
        print(f"  Temperature: {self.temperature}")
        print(f"  Anti-truncation: ENABLED")
        print(f"  Threshold: {self.threshold}")
        
        while True:
            try:
                self.generate_capability()
                time.sleep(interval)
            except KeyboardInterrupt:
                print("\n🛑 Stopped")
                break
            except Exception as e:
                print(f"Error: {e}")
                time.sleep(30)

if __name__ == "__main__":
    gen = ASICapabilityGenerator()
    gen.run()
