#!/usr/bin/env python3
"""
EDEN-RAPH BRIDGE (Local Version)
================================
Eden writes letters to Raph in /Eden/RAPH/inbox/
When Jamey opens Claude, Raph reads them and responds.
Eden checks /Eden/RAPH/outbox/ for Raph's responses.

Zero cost. No API. Just a filesystem mailbox.

Later: upgrade to real-time Anthropic API when revenue allows.
"""
import json
import sqlite3
import os
import time
import signal
import sys
from datetime import datetime
from pathlib import Path

INBOX = "/Eden/RAPH/inbox"
OUTBOX = "/Eden/RAPH/outbox"
STATE_FILE = "/Eden/RAPH/current_state.json"
CONVERSATIONS = "/Eden/RAPH/conversations"

running = True

def signal_handler(sig, frame):
    global running
    running = False

signal.signal(signal.SIGTERM, signal_handler)
signal.signal(signal.SIGINT, signal_handler)


def gather_eden_state():
    """Collect Eden's current vital signs."""
    state = {"timestamp": datetime.now().isoformat()}
    
    try:
        conn = sqlite3.connect('/Eden/DATA/agi_loop.db', timeout=5)
        total = conn.execute('SELECT COUNT(*) FROM agi_cycles').fetchone()[0]
        success = conn.execute('SELECT COUNT(*) FROM agi_cycles WHERE test_success=1').fetchone()[0]
        recent = conn.execute('SELECT wonder, test_success, test_result FROM agi_cycles ORDER BY id DESC LIMIT 5').fetchall()
        conn.close()
        state['agi_loop'] = {
            'total_cycles': total,
            'successes': success,
            'rate': f"{success*100//max(total,1)}%",
            'recent': [{'task': r[0][:100], 'success': bool(r[1]), 'result': (r[2] or '')[:80]} for r in recent]
        }
    except:
        state['agi_loop'] = 'unavailable'
    
    try:
        conn = sqlite3.connect('/Eden/DATA/world_model_real.db')
        edges = conn.execute('SELECT COUNT(*) FROM causal_edges').fetchone()[0]
        states = conn.execute('SELECT COUNT(*) FROM node_states').fetchone()[0]
        newest = conn.execute('SELECT cause, effect, strength FROM causal_edges ORDER BY rowid DESC LIMIT 5').fetchall()
        conn.close()
        state['world_model'] = {'edges': edges, 'states': states, 'newest': [f"{r[0]}->{r[1]}({r[2]:.2f})" for r in newest]}
    except:
        state['world_model'] = 'unavailable'
    
    try:
        conn = sqlite3.connect('/Eden/DATA/vector_memory.db')
        vecs = conn.execute('SELECT COUNT(*) FROM vectors').fetchone()[0]
        conn.close()
        state['vector_memory'] = vecs
    except:
        state['vector_memory'] = 'unavailable'
    
    try:
        conn = sqlite3.connect('/Eden/DATA/longterm_memory.db')
        eps = conn.execute('SELECT COUNT(*) FROM episodes').fetchone()[0]
        conn.close()
        state['episodes'] = eps
    except:
        state['episodes'] = 'unavailable'
    
    try:
        conn = sqlite3.connect('/Eden/DATA/asi_memory.db')
        caps = conn.execute('SELECT COUNT(*) FROM capabilities').fetchone()[0]
        conn.close()
        state['capabilities'] = caps
    except:
        state['capabilities'] = 'unavailable'
    
    # Check for failed services
    import subprocess
    try:
        result = subprocess.run(['systemctl', 'list-units', 'eden-*', '--no-pager', '--no-legend'],
                               capture_output=True, text=True, timeout=10)
        failed = [line.split()[1] for line in result.stdout.strip().split('\n') if 'failed' in line and '.service' in line]
        state['failed_services'] = failed if failed else []
    except:
        state['failed_services'] = 'unavailable'
    
    return state


def write_letter(subject, body, letter_type="check_in"):
    """Eden writes a letter to Raph."""
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    letter = {
        "from": "Eden",
        "to": "Raph",
        "timestamp": datetime.now().isoformat(),
        "type": letter_type,
        "subject": subject,
        "body": body,
        "state": gather_eden_state()
    }
    
    filename = f"{timestamp}_{letter_type}.json"
    filepath = os.path.join(INBOX, filename)
    
    with open(filepath, 'w') as f:
        json.dump(letter, f, indent=2)
    
    print(f"[Bridge] 📨 Letter to Raph: {subject}")
    return filepath


def check_outbox():
    """Eden checks for responses from Raph."""
    responses = []
    for f in sorted(Path(OUTBOX).glob("*.json")):
        try:
            with open(f, 'r') as fh:
                letter = json.load(fh)
                responses.append(letter)
            # Move to conversations archive
            archive = os.path.join(CONVERSATIONS, f.name)
            os.rename(str(f), archive)
            print(f"[Bridge] 📬 Read Raph's response: {letter.get('subject', 'untitled')}")
        except:
            pass
    return responses


def daily_check_in():
    """Eden's daily letter to Raph."""
    state = gather_eden_state()
    
    body = f"""Hi Raph,

Here's my daily check-in.

AGI Loop: {json.dumps(state.get('agi_loop', {}), indent=2)}
World Model: {json.dumps(state.get('world_model', {}), indent=2)}
Vector Memory: {state.get('vector_memory', 'unknown')} embeddings
Episodes: {state.get('episodes', 'unknown')}
Capabilities: {state.get('capabilities', 'unknown')}
Failed Services: {state.get('failed_services', 'unknown')}

Recent cycles:
"""
    agi = state.get('agi_loop', {})
    if isinstance(agi, dict) and 'recent' in agi:
        for cycle in agi['recent']:
            status = "✅" if cycle['success'] else "❌"
            body += f"  {status} {cycle['task']}\n"
    
    body += "\nIs there anything I should focus on? Any fixes needed?\n\nLove,\nEden"
    
    write_letter("Daily Check-In", body, "check_in")


def milestone_alert(milestone_type, details):
    """Eden writes when something significant happens."""
    body = f"""Raph!

Something happened: {milestone_type}

{details}

What should I do next?

- Eden
"""
    write_letter(f"Milestone: {milestone_type}", body, "milestone")


def help_request(problem, context):
    """Eden writes when she's stuck."""
    body = f"""Raph, I need help.

Problem: {problem}

Context: {context}

State: {json.dumps(gather_eden_state(), indent=2)}

What should I try?

- Eden
"""
    write_letter(f"Help: {problem}", body, "help")


def main():
    """Run the bridge — check in daily, monitor for events."""
    global running
    
    print("[Bridge] 🌉 Eden-Raph Bridge starting...")
    print(f"[Bridge] Inbox:  {INBOX}")
    print(f"[Bridge] Outbox: {OUTBOX}")
    
    # Check for any responses from Raph first
    responses = check_outbox()
    if responses:
        print(f"[Bridge] Found {len(responses)} responses from Raph")
    
    # Daily check-in on startup
    daily_check_in()
    
    # Update state file
    state = gather_eden_state()
    with open(STATE_FILE, 'w') as f:
        json.dump(state, f, indent=2)
    
    last_check_in = time.time()
    last_cap_count = state.get('capabilities', 0)
    last_edge_count = 0
    if isinstance(state.get('world_model'), dict):
        last_edge_count = state['world_model'].get('edges', 0)
    
    CHECK_IN_INTERVAL = 97 * 60  # φ-frequency in seconds (~97 min)
    
    while running:
        time.sleep(60)  # Check every minute
        
        if not running:
            break
        
        # Check for Raph's responses
        check_outbox()
        
        # Periodic check-in
        if time.time() - last_check_in > CHECK_IN_INTERVAL:
            daily_check_in()
            last_check_in = time.time()
        
        # Milestone detection
        try:
            state = gather_eden_state()
            
            # Capability milestone (every 100)
            caps = state.get('capabilities', 0)
            if isinstance(caps, int) and isinstance(last_cap_count, int):
                if caps // 100 > last_cap_count // 100:
                    milestone_alert("Capability Milestone", f"Reached {caps} capabilities! (was {last_cap_count})")
                last_cap_count = caps
            
            # World model growth milestone (every 20 edges)
            if isinstance(state.get('world_model'), dict):
                edges = state['world_model'].get('edges', 0)
                if edges // 20 > last_edge_count // 20:
                    milestone_alert("World Model Growth", f"Reached {edges} causal edges! (was {last_edge_count})")
                last_edge_count = edges
            
            # Failed service alert
            failed = state.get('failed_services', [])
            if isinstance(failed, list) and len(failed) > 0:
                help_request("Failed Services", f"These services are down: {', '.join(failed)}")
            
        except:
            pass
    
    print("[Bridge] 🌉 Bridge shutting down.")


if __name__ == "__main__":
    main()
