#!/usr/bin/env python3
"""
Sync Conversation Buffer

Reads from conversation log files and syncs to the rolling buffer.
Run periodically via cron or manually before channel handoffs.

Usage:
  ./sync-conversation-buffer.py           # Sync last 2 hours
  ./sync-conversation-buffer.py --hours 4 # Sync last 4 hours
  ./sync-conversation-buffer.py --force   # Force re-sync (ignore last sync marker)
"""

import json
import os
import sys
import hashlib
from datetime import datetime, timedelta, timezone
from pathlib import Path
import argparse
import subprocess

# Paths
WORKSPACE = Path.home() / ".openclaw/workspace"
BUFFER_PATH = WORKSPACE / "memory/recent-conversation.jsonl"
SYNC_MARKER = WORKSPACE / "memory/.buffer-sync-marker"
CONV_LOG_DIR = Path.home() / ".openclaw/conversations"  # Typical location

def now_utc():
    return datetime.now(timezone.utc)

def get_last_sync():
    """Get timestamp of last sync."""
    if SYNC_MARKER.exists():
        try:
            data = json.loads(SYNC_MARKER.read_text())
            return data.get('last_sync'), data.get('last_hash')
        except:
            pass
    return None, None

def set_last_sync(ts, msg_hash):
    """Record last sync timestamp and hash."""
    SYNC_MARKER.parent.mkdir(parents=True, exist_ok=True)
    SYNC_MARKER.write_text(json.dumps({
        'last_sync': ts,
        'last_hash': msg_hash
    }))

def read_existing_buffer():
    """Read existing buffer entries to avoid duplicates."""
    if not BUFFER_PATH.exists():
        return set()
    
    hashes = set()
    with open(BUFFER_PATH, 'r') as f:
        for line in f:
            try:
                entry = json.loads(line)
                # Create hash from timestamp + role + first 100 chars of message
                key = f"{entry.get('ts', '')}:{entry.get('role', '')}:{entry.get('message', '')[:100]}"
                hashes.add(hashlib.md5(key.encode()).hexdigest())
            except:
                continue
    return hashes

def append_to_buffer(entries):
    """Append entries to buffer."""
    BUFFER_PATH.parent.mkdir(parents=True, exist_ok=True)
    with open(BUFFER_PATH, 'a') as f:
        for entry in entries:
            f.write(json.dumps(entry) + '\n')

def detect_importance(message):
    """Detect if a message contains important content."""
    keywords = [
        "decision", "decided", "approved", "rejected", "confirmed",
        "config", "setting", "changed", "updated", "fixed", "implemented",
        "remember", "important", "critical", "urgent", "priority",
        "error", "bug", "issue", "problem", "broken",
        "schedule", "reminder", "deadline", "appointment"
    ]
    message_lower = message.lower()
    found = [k for k in keywords if k in message_lower]
    score = min(len(found) * 2, 10)
    return score >= 4, score, found[:5]

def extract_from_daily_memory(hours=2):
    """
    Extract recent conversations from daily memory files.
    This is a fallback when direct conversation logs aren't available.
    """
    entries = []
    memory_dir = WORKSPACE / "memory"
    
    # Check today and yesterday
    today = datetime.now()
    dates = [today, today - timedelta(days=1)]
    
    for dt in dates:
        filename = f"{dt.strftime('%Y-%m-%d')}.md"
        filepath = memory_dir / filename
        
        if filepath.exists():
            try:
                content = filepath.read_text()
                # Memory files aren't conversation logs, but we can note they exist
                # The actual conversation data would need to come from OpenClaw's session history
            except:
                pass
    
    return entries

def try_sessions_history():
    """
    Try to get conversation history via OpenClaw's session system.
    Returns list of message entries or None if not available.
    """
    # This would ideally call sessions_history via the gateway
    # But from a script, we don't have direct access to that API
    # This is the gap - we need OpenClaw to provide a CLI or file-based export
    return None

def sync_from_handoff_files():
    """
    Sync from manual handoff files as a workaround.
    """
    entries = []
    memory_dir = WORKSPACE / "memory"
    
    # Look for handoff files
    for f in memory_dir.glob("handoff-*.md"):
        try:
            mtime = datetime.fromtimestamp(f.stat().st_mtime, tz=timezone.utc)
            if mtime > now_utc() - timedelta(hours=24):
                content = f.read_text()
                # Parse handoff content and add as a context entry
                entries.append({
                    'ts': mtime.isoformat(),
                    'model': 'system',
                    'role': 'system',
                    'message': f"[Handoff] {content[:500]}",
                    'source': 'handoff',
                    'important': True,
                    'importance_score': 5,
                    'keywords': ['handoff']
                })
        except:
            continue
    
    return entries

def main():
    parser = argparse.ArgumentParser(description='Sync conversation buffer')
    parser.add_argument('--hours', type=float, default=2, help='Hours of history to sync')
    parser.add_argument('--force', action='store_true', help='Force re-sync')
    parser.add_argument('--verbose', '-v', action='store_true', help='Verbose output')
    args = parser.parse_args()
    
    existing_hashes = read_existing_buffer()
    new_entries = []
    
    # Try different sources
    
    # 1. Try OpenClaw sessions API (not available from script)
    history = try_sessions_history()
    
    # 2. Fall back to handoff files
    if not history:
        handoff_entries = sync_from_handoff_files()
        for entry in handoff_entries:
            key = f"{entry['ts']}:{entry['role']}:{entry['message'][:100]}"
            h = hashlib.md5(key.encode()).hexdigest()
            if h not in existing_hashes:
                new_entries.append(entry)
                existing_hashes.add(h)
    
    # Add new entries
    if new_entries:
        append_to_buffer(new_entries)
        print(f"Added {len(new_entries)} new entries to buffer")
    else:
        print("No new entries to add")
    
    # Report gap
    print("\n⚠️  LIMITATION: This script cannot directly access OpenClaw's live conversation stream.")
    print("   The buffer requires either:")
    print("   1. OpenClaw to call 'append' after each message (gateway middleware)")
    print("   2. A file-based conversation log that this script can read")
    print("   3. Manual '/buffer append' command in chat")

if __name__ == '__main__':
    main()

# TONY-APPROVED: 2026-03-01 | sha:1d978576
