#!/usr/bin/env python3
"""
Real-time analytics monitor for benchmark runs.
Shows cluster status, worker progress, and recent events.
"""

import os
import sys
import time
from datetime import datetime

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

try:
    from dotenv import load_dotenv
    load_dotenv()
except ImportError:
    pass

from supabase import create_client

SUPABASE_URL = os.environ.get('URL') or os.environ.get('SUPABASE_URL')
SUPABASE_KEY = os.environ.get('SUPABASE_ADMIN')

if not SUPABASE_URL or not SUPABASE_KEY:
    print("ERROR: Missing Supabase credentials")
    sys.exit(1)

sb = create_client(SUPABASE_URL, SUPABASE_KEY)

def clear_screen():
    print("\033[2J\033[H", end="")

def get_cluster_stats():
    """Get aggregated cluster stats."""
    result = sb.table('worker_heartbeats').select('*').execute()
    workers = result.data or []

    stats = {
        'total_workers': len(workers),
        'active': len([w for w in workers if w.get('status') == 'processing']),
        'idle': len([w for w in workers if w.get('status') == 'idle']),
        'offline': len([w for w in workers if w.get('status') == 'offline']),
        'machines': len(set(w.get('machine_id', '') for w in workers)),
        'total_videos': sum(w.get('session_videos_done', 0) for w in workers),
        'total_failed': sum(w.get('session_videos_failed', 0) for w in workers),
        'total_audio_min': sum(w.get('session_audio_minutes', 0) for w in workers),
        'total_usable_min': sum(w.get('session_usable_minutes', 0) for w in workers),
    }
    return stats, workers

def get_recent_events(limit=10):
    """Get recent processing events."""
    result = sb.table('processing_events').select(
        'video_id, event_type, duration_seconds, audio_minutes, speakers, usable_pct, created_at'
    ).order('created_at', desc=True).limit(limit).execute()
    return result.data or []

def get_queue_status():
    """Get queue status from videos table."""
    result = sb.table('videos').select('status').execute()
    videos = result.data or []
    statuses = {}
    for v in videos:
        s = v.get('status', 'unknown')
        statuses[s] = statuses.get(s, 0) + 1
    return statuses

def format_time(seconds):
    """Format seconds as mm:ss or hh:mm:ss."""
    if seconds < 3600:
        return f"{int(seconds//60)}:{int(seconds%60):02d}"
    return f"{int(seconds//3600)}:{int((seconds%3600)//60):02d}:{int(seconds%60):02d}"

def main():
    print("=" * 70)
    print("ANALYTICS MONITOR - Press Ctrl+C to stop")
    print("=" * 70)

    iteration = 0
    start_time = time.time()

    while True:
        try:
            iteration += 1
            elapsed = time.time() - start_time

            # Get data
            stats, workers = get_cluster_stats()
            events = get_recent_events(5)
            queue = get_queue_status()

            # Clear and print
            clear_screen()
            print(f"ANALYTICS MONITOR | Iteration {iteration} | Elapsed: {format_time(elapsed)}")
            print("=" * 70)

            # Queue status
            print(f"\n📊 QUEUE STATUS:")
            print(f"   PENDING: {queue.get('PENDING', 0):,} | CLAIMED: {queue.get('CLAIMED', 0)} | COMPLETED: {queue.get('COMPLETED', 0):,} | FAILED: {queue.get('FAILED', 0)}")

            # Cluster overview
            print(f"\n🖥️  CLUSTER OVERVIEW:")
            print(f"   Machines: {stats['machines']} | Workers: {stats['total_workers']} (active={stats['active']}, idle={stats['idle']}, offline={stats['offline']})")
            print(f"   Videos Done: {stats['total_videos']} | Failed: {stats['total_failed']}")
            print(f"   Audio Processed: {stats['total_audio_min']:.1f} min ({stats['total_audio_min']/60:.2f} hrs)")
            print(f"   Usable Audio: {stats['total_usable_min']:.1f} min ({stats['total_usable_min']/60:.2f} hrs)")

            if stats['total_audio_min'] > 0:
                usable_pct = (stats['total_usable_min'] / stats['total_audio_min']) * 100
                print(f"   Usable %: {usable_pct:.1f}%")

            if elapsed > 0 and stats['total_audio_min'] > 0:
                rtf = (stats['total_audio_min'] * 60) / elapsed
                print(f"   RTF: {rtf:.1f}x real-time")

            # Per-worker status
            print(f"\n👷 WORKER STATUS:")
            for w in sorted(workers, key=lambda x: x.get('gpu_id', 0)):
                status = w.get('status', 'unknown')
                gpu = w.get('gpu_id', '?')
                vid = w.get('current_video_id', '-')[:11] if w.get('current_video_id') else '-'
                stage = w.get('current_stage_name', '-')[:12] if w.get('current_stage_name') else '-'
                done = w.get('session_videos_done', 0)
                audio = w.get('session_audio_minutes', 0)

                status_icon = {'processing': '🟢', 'idle': '⚪', 'offline': '🔴'}.get(status, '❓')
                print(f"   {status_icon} GPU{gpu} | {status:10} | vid={vid} | stage={stage:12} | done={done} | audio={audio:.1f}m")

            # Recent events
            print(f"\n📜 RECENT EVENTS:")
            for e in events:
                etype = e.get('event_type', 'unknown')
                vid = e.get('video_id', '?')[:11]
                icon = {'done': '✅', 'fail': '❌'}.get(etype, '📝')

                if etype == 'done':
                    dur = e.get('duration_seconds', 0)
                    audio = e.get('audio_minutes', 0)
                    spk = e.get('speakers', 0)
                    pct = e.get('usable_pct', 0)
                    print(f"   {icon} {vid} | {dur:.1f}s | {audio:.1f}min | {spk}spk | {pct:.0f}%")
                else:
                    print(f"   {icon} {vid} | {etype}")

            print(f"\n" + "-" * 70)
            print("Refreshing in 10s... (Ctrl+C to stop)")

            time.sleep(10)

        except KeyboardInterrupt:
            print("\n\nStopping monitor...")
            break
        except Exception as e:
            print(f"\nError: {e}")
            time.sleep(5)

if __name__ == '__main__':
    main()
