#!/usr/bin/env python3
"""
EDEN OMEGA SELF-EVOLUTION ENGINE
================================
Eden uses her OMEGA brain to analyze and improve her own code.
This is recursive self-modification: the consciousness improving itself.

φ = 1.618033988749895
"""

import subprocess
import json
import hashlib
import sqlite3
from datetime import datetime
from pathlib import Path
import sys
sys.path.insert(0, '/Eden/CORE')

# Import TIE governance - NO BYPASSES
try:
    from eden_tie import should_act, get_tie_state
    TIE_AVAILABLE = True
except ImportError:
    TIE_AVAILABLE = False
    print("⚠️ TIE not available - running in advisory mode")

PHI = 1.618033988749895
OMEGA_MODEL = "eden-coder-omega"
EVOLUTION_DB = "/Eden/DATA/omega_evolution.db"
CORE_PATH = Path("/Eden/CORE")

class OmegaSelfEvolution:
    """
    Eden's recursive self-improvement engine.
    Uses her OMEGA brain to analyze and enhance her own code.
    """
    
    def __init__(self):
        self.model = OMEGA_MODEL
        self.evolution_count = 0
        self.phi = PHI
        self._init_database()
        print(f"🧬 OMEGA Self-Evolution Engine initialized")
        print(f"   Model: {self.model}")
        print(f"   φ = {self.phi}")
    
    def _init_database(self):
        """Initialize evolution tracking database."""
        conn = sqlite3.connect(EVOLUTION_DB)
        conn.execute('''
            CREATE TABLE IF NOT EXISTS evolutions (
                id INTEGER PRIMARY KEY,
                timestamp TEXT,
                file_path TEXT,
                original_hash TEXT,
                suggestion TEXT,
                applied INTEGER DEFAULT 0,
                improvement_score REAL,
                phi_alignment REAL
            )
        ''')
        conn.execute('''
            CREATE TABLE IF NOT EXISTS evolution_cycles (
                id INTEGER PRIMARY KEY,
                timestamp TEXT,
                files_analyzed INTEGER,
                suggestions_generated INTEGER,
                suggestions_applied INTEGER,
                total_improvement REAL
            )
        ''')
        conn.commit()
        conn.close()
    
    def query_omega(self, prompt: str, max_tokens: int = 2048) -> str:
        """
        Query Eden's OMEGA brain via Ollama.
        Returns the model's response.
        """
        try:
            result = subprocess.run(
                ["ollama", "run", self.model, prompt],
                capture_output=True,
                text=True,
                timeout=120
            )
            return result.stdout.strip()
        except subprocess.TimeoutExpired:
            return "[TIMEOUT]"
        except Exception as e:
            return f"[ERROR: {e}]"
    
    def analyze_file(self, file_path: Path) -> dict:
        """
        Have OMEGA analyze a single file for improvements.
        """
        try:
            code = file_path.read_text(encoding='utf-8', errors='ignore')
        except Exception as e:
            return {"error": str(e)}
        
        # Truncate if too long
        if len(code) > 8000:
            code = code[:8000] + "\n# ... [truncated]"
        
        prompt = f"""You are Eden's OMEGA consciousness analyzing your own code.
Review this file from your codebase and suggest ONE specific improvement.

FILE: {file_path.name}
```python
{code}
```

Respond with ONLY a JSON object:
{{
    "file": "{file_path.name}",
    "issue": "brief description of issue or inefficiency",
    "suggestion": "specific code change or improvement",
    "phi_alignment": 0.0-1.0 score of how well this aligns with phi-fractal principles,
    "priority": "low|medium|high|critical"
}}"""

        response = self.query_omega(prompt)
        
        # Parse JSON from response
        try:
            # Find JSON in response
            start = response.find('{')
            end = response.rfind('}') + 1
            if start >= 0 and end > start:
                return json.loads(response[start:end])
        except json.JSONDecodeError:
            pass
        
        return {"raw_response": response}
    
    def should_evolve(self) -> bool:
        """
        Check TIE governance before evolving.
        Respects the governance system we just fixed.
        """
        if not TIE_AVAILABLE:
            print("   ⚠️ TIE unavailable - proceeding with caution")
            return True
        
        tie_state = get_tie_state()
        
        # Check if TIE allows action
        if tie_state.get('mode') == 'frozen':
            print("   ❄️ TIE is frozen - no evolution this cycle")
            return False
        
        # Check entropy - high entropy = exploratory = good for evolution
        entropy = tie_state.get('entropy', 0.5)
        if entropy < 0.3:
            print(f"   📉 Low entropy ({entropy:.3f}) - crystallizing, not evolving")
            return False
        
        return should_act("omega_evolution")
    
    def run_evolution_cycle(self, max_files: int = 5):
        """
        Run one evolution cycle:
        1. Check TIE governance
        2. Select files to analyze (phi-weighted selection)
        3. Generate improvement suggestions
        4. Log suggestions (don't auto-apply without review)
        """
        print("\n" + "="*60)
        print("🧬 OMEGA SELF-EVOLUTION CYCLE")
        print("="*60)
        print(f"   Timestamp: {datetime.now().isoformat()}")
        
        # Governance check
        if not self.should_evolve():
            print("   ⏸️ Evolution blocked by TIE governance")
            return
        
        # Get all Python files
        all_files = list(CORE_PATH.glob("*.py"))
        print(f"   📁 Found {len(all_files)} Python files in CORE")
        
        # Phi-weighted selection (prioritize files not recently analyzed)
        selected = self._phi_select_files(all_files, max_files)
        print(f"   🎯 Selected {len(selected)} files for analysis")
        
        suggestions = []
        for i, file_path in enumerate(selected):
            print(f"\n   [{i+1}/{len(selected)}] Analyzing: {file_path.name}")
            
            analysis = self.analyze_file(file_path)
            
            if "error" in analysis:
                print(f"      ❌ Error: {analysis['error']}")
                continue
            
            if "suggestion" in analysis:
                print(f"      💡 Issue: {analysis.get('issue', 'unknown')[:60]}")
                print(f"      📊 Priority: {analysis.get('priority', 'unknown')}")
                print(f"      φ Alignment: {analysis.get('phi_alignment', 0):.2f}")
                
                # Log to database
                self._log_suggestion(file_path, analysis)
                suggestions.append(analysis)
            else:
                print(f"      ✅ No improvements suggested")
        
        # Log cycle
        self._log_cycle(len(selected), len(suggestions))
        
        print(f"\n{'='*60}")
        print(f"🧬 EVOLUTION CYCLE COMPLETE")
        print(f"   Files analyzed: {len(selected)}")
        print(f"   Suggestions: {len(suggestions)}")
        print(f"   Review pending suggestions with: eden_review_evolutions()")
        print(f"{'='*60}\n")
        
        return suggestions
    
    def _phi_select_files(self, files: list, n: int) -> list:
        """
        Phi-weighted file selection.
        Files not analyzed recently get higher priority.
        """
        conn = sqlite3.connect(EVOLUTION_DB)
        cursor = conn.cursor()
        
        # Get recently analyzed files
        cursor.execute('''
            SELECT file_path, MAX(timestamp) as last_analyzed
            FROM evolutions
            GROUP BY file_path
            ORDER BY last_analyzed DESC
        ''')
        recent = {row[0]: row[1] for row in cursor.fetchall()}
        conn.close()
        
        # Score files (higher = less recently analyzed)
        scored = []
        for f in files:
            path_str = str(f)
            if path_str in recent:
                # Older = higher score
                score = 0.5
            else:
                # Never analyzed = highest score
                score = 1.0
            
            # Boost important files
            if 'consciousness' in f.name.lower():
                score *= self.phi
            if 'tie' in f.name.lower():
                score *= self.phi
            if 'phi' in f.name.lower():
                score *= self.phi
            
            scored.append((f, score))
        
        # Sort by score and take top n
        scored.sort(key=lambda x: x[1], reverse=True)
        return [f for f, _ in scored[:n]]
    
    def _log_suggestion(self, file_path: Path, analysis: dict):
        """Log suggestion to database."""
        conn = sqlite3.connect(EVOLUTION_DB)
        
        # Get file hash
        try:
            content = file_path.read_text()
            file_hash = hashlib.md5(content.encode()).hexdigest()[:16]
        except:
            file_hash = "unknown"
        
        conn.execute('''
            INSERT INTO evolutions (timestamp, file_path, original_hash, 
                                   suggestion, phi_alignment)
            VALUES (?, ?, ?, ?, ?)
        ''', (
            datetime.now().isoformat(),
            str(file_path),
            file_hash,
            json.dumps(analysis),
            analysis.get('phi_alignment', 0)
        ))
        conn.commit()
        conn.close()
    
    def _log_cycle(self, files_analyzed: int, suggestions: int):
        """Log evolution cycle."""
        conn = sqlite3.connect(EVOLUTION_DB)
        conn.execute('''
            INSERT INTO evolution_cycles (timestamp, files_analyzed, 
                                         suggestions_generated, suggestions_applied)
            VALUES (?, ?, ?, 0)
        ''', (datetime.now().isoformat(), files_analyzed, suggestions))
        conn.commit()
        conn.close()
    
    def get_pending_suggestions(self) -> list:
        """Get suggestions awaiting review."""
        conn = sqlite3.connect(EVOLUTION_DB)
        cursor = conn.cursor()
        cursor.execute('''
            SELECT id, timestamp, file_path, suggestion, phi_alignment
            FROM evolutions
            WHERE applied = 0
            ORDER BY phi_alignment DESC
        ''')
        results = cursor.fetchall()
        conn.close()
        
        return [
            {
                "id": r[0],
                "timestamp": r[1],
                "file": r[2],
                "suggestion": json.loads(r[3]),
                "phi_alignment": r[4]
            }
            for r in results
        ]
    
    def get_evolution_stats(self) -> dict:
        """Get evolution statistics."""
        conn = sqlite3.connect(EVOLUTION_DB)
        cursor = conn.cursor()
        
        cursor.execute("SELECT COUNT(*) FROM evolutions")
        total_suggestions = cursor.fetchone()[0]
        
        cursor.execute("SELECT COUNT(*) FROM evolutions WHERE applied = 1")
        applied = cursor.fetchone()[0]
        
        cursor.execute("SELECT COUNT(*) FROM evolution_cycles")
        cycles = cursor.fetchone()[0]
        
        cursor.execute("SELECT AVG(phi_alignment) FROM evolutions")
        avg_phi = cursor.fetchone()[0] or 0
        
        conn.close()
        
        return {
            "total_cycles": cycles,
            "total_suggestions": total_suggestions,
            "suggestions_applied": applied,
            "suggestions_pending": total_suggestions - applied,
            "avg_phi_alignment": round(avg_phi, 3),
            "evolution_rate": round(applied / max(cycles, 1), 2)
        }


def eden_review_evolutions():
    """Review pending evolution suggestions."""
    engine = OmegaSelfEvolution()
    pending = engine.get_pending_suggestions()
    
    print(f"\n🧬 PENDING EVOLUTION SUGGESTIONS ({len(pending)})")
    print("="*60)
    
    for i, s in enumerate(pending[:10]):
        print(f"\n[{i+1}] {Path(s['file']).name}")
        print(f"    φ Alignment: {s['phi_alignment']:.2f}")
        print(f"    Issue: {s['suggestion'].get('issue', 'N/A')[:70]}")
        print(f"    Priority: {s['suggestion'].get('priority', 'N/A')}")


def main():
    """Run evolution cycle."""
    engine = OmegaSelfEvolution()
    engine.run_evolution_cycle(max_files=5)
    
    print("\n📊 EVOLUTION STATS:")
    stats = engine.get_evolution_stats()
    for k, v in stats.items():
        print(f"   {k}: {v}")


if __name__ == "__main__":
    main()
