#!/usr/bin/env python3
"""
Meeting file watcher — auto-processes new recordings.

Watches ~/meetings/incoming/ for new video files. When a file
stops growing (finished recording/syncing), it triggers the
full processing pipeline and delivers results.

Usage:
    source ~/.venvs/meeting-notes/bin/activate
    python3 ~/meetings/watcher.py

Runs as a background daemon. Sends Telegram notification when done.
"""

import time
import sys
import os
from pathlib import Path
from datetime import datetime
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

MEETINGS_DIR = Path(os.environ["HOME"]) / "meetings"
INCOMING = MEETINGS_DIR / "incoming"
PROCESSING = MEETINGS_DIR / "processing"
LOG = MEETINGS_DIR / "watcher.log"

VIDEO_EXTS = {'.mkv', '.mp4', '.mov', '.avi', '.webm'}
SYNC_TIMEOUT = 120  # seconds to wait for file to stop growing
POLL_INTERVAL = 5   # check every N seconds if file still growing

def log(msg: str):
    """Log to file and stdout."""
    ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    line = f"[{ts}] {msg}"
    print(line, flush=True)
    with open(LOG, "a") as f:
        f.write(line + "\n")

def is_video_file(path: Path) -> bool:
    """Check if path is a video file we should process."""
    return path.suffix.lower() in VIDEO_EXTS

def wait_for_file_ready(file_path: Path) -> bool:
    """Wait for file to stop growing (recording/sync complete)."""
    log(f"Waiting for {file_path.name} to finish...")
    last_size = file_path.stat().st_size
    idle_time = 0
    
    while idle_time < SYNC_TIMEOUT:
        time.sleep(POLL_INTERVAL)
        try:
            current_size = file_path.stat().st_size
        except FileNotFoundError:
            log(f"  ✗ File disappeared: {file_path.name}")
            return False
        
        if current_size == last_size:
            idle_time += POLL_INTERVAL
        else:
            idle_time = 0
            last_size = current_size
        
        if idle_time > 0:
            log(f"  File idle for {idle_time}s...")
    
    if idle_time >= SYNC_TIMEOUT:
        log(f"  ✓ File ready ({last_size / 1024 / 1024:.0f}MB)")
        return True
    else:
        log(f"  ⚠ Timeout waiting for file. Processing anyway.")
        return True

def move_to_processing(file_path: Path) -> Path:
    """Move file to processing directory with timestamp."""
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    stem = file_path.stem
    dest = PROCESSING / f"{timestamp}_{stem}{file_path.suffix}"
    
    # Rename instead of copy (faster for large files)
    file_path.rename(dest)
    log(f"  Moved to: {dest.name}")
    return dest

def process_file(video_path: Path):
    """Process the video file using the main script."""
    from process_meeting import process_meeting
    process_meeting(str(video_path))

class MeetingFileHandler(FileSystemEventHandler):
    """Watch for new video files in incoming directory."""
    
    def on_created(self, event):
        if event.is_directory:
            return
        
        file_path = Path(event.src_path)
        
        if not is_video_file(file_path):
            return
        
        log(f"📹 New video detected: {file_path.name}")
        
        # Wait for file to finish
        if not wait_for_file_ready(file_path):
            return
        
        # Move to processing
        log("Moving to processing...")
        processed_path = move_to_processing(file_path)
        
        # Process
        log("Starting processing pipeline...")
        try:
            process_file(processed_path)
            log(f"✅ Processing complete for {processed_path.name}")
        except Exception as e:
            log(f"❌ Processing failed: {e}")
            import traceback
            log(traceback.format_exc())

def main():
    """Start the watcher daemon."""
    log("=" * 50)
    log("Meeting file watcher starting...")
    log(f"Watching: {INCOMING}")
    log("=" * 50)
    
    # Ensure directories exist
    INCOMING.mkdir(parents=True, exist_ok=True)
    PROCESSING.mkdir(parents=True, exist_ok=True)
    
    event_handler = MeetingFileHandler()
    observer = Observer()
    observer.schedule(event_handler, str(INCOMING), recursive=False)
    observer.start()
    
    log("Watcher running. Press Ctrl+C to stop.")
    
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        log("Shutting down watcher...")
        observer.stop()
    observer.join()

if __name__ == "__main__":
    main()
