#!/usr/bin/env python3
"""
Simple file watcher - monitors workspace for changes and logs them.
Uses polling (no external dependencies).
"""

import os
import sys
import time
import json
from datetime import datetime
from pathlib import Path
from collections import defaultdict

WORKSPACE = Path("/home/wdjones/.openclaw/workspace")
STATE_FILE = WORKSPACE / ".watcher-state.json"
LOG_FILE = WORKSPACE / "memory" / "file-changes.log"

IGNORE_PATTERNS = {'.git', '__pycache__', 'node_modules', '.venv', 'venv', '.watcher-state.json'}
IGNORE_EXTENSIONS = {'.pyc', '.pyo', '.log'}

def should_ignore(path: Path) -> bool:
    """Check if path should be ignored."""
    parts = path.parts
    for pattern in IGNORE_PATTERNS:
        if pattern in parts:
            return True
    if path.suffix in IGNORE_EXTENSIONS:
        return True
    return False

def get_file_state() -> dict:
    """Get current state of all files."""
    state = {}
    for root, dirs, files in os.walk(WORKSPACE):
        # Filter directories
        dirs[:] = [d for d in dirs if d not in IGNORE_PATTERNS and not d.startswith('.')]
        
        for fname in files:
            fpath = Path(root) / fname
            if should_ignore(fpath):
                continue
            
            try:
                stat = fpath.stat()
                rel_path = str(fpath.relative_to(WORKSPACE))
                state[rel_path] = {
                    'mtime': stat.st_mtime,
                    'size': stat.st_size,
                }
            except:
                pass
    
    return state

def load_state() -> dict:
    """Load previous state from file."""
    if STATE_FILE.exists():
        try:
            with open(STATE_FILE) as f:
                return json.load(f)
        except:
            pass
    return {}

def save_state(state: dict):
    """Save current state to file."""
    with open(STATE_FILE, 'w') as f:
        json.dump(state, f)

def log_change(change_type: str, path: str):
    """Log a change to the log file."""
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    line = f"[{timestamp}] {change_type}: {path}\n"
    
    LOG_FILE.parent.mkdir(parents=True, exist_ok=True)
    with open(LOG_FILE, 'a') as f:
        f.write(line)
    
    print(line.strip())

def diff_states(old: dict, new: dict) -> dict:
    """Compare states and return changes."""
    changes = {'added': [], 'modified': [], 'deleted': []}
    
    old_keys = set(old.keys())
    new_keys = set(new.keys())
    
    # Added files
    for path in new_keys - old_keys:
        changes['added'].append(path)
    
    # Deleted files
    for path in old_keys - new_keys:
        changes['deleted'].append(path)
    
    # Modified files
    for path in old_keys & new_keys:
        if old[path]['mtime'] != new[path]['mtime'] or old[path]['size'] != new[path]['size']:
            changes['modified'].append(path)
    
    return changes

def watch(interval: int = 5):
    """Watch for changes continuously."""
    print(f"Watching {WORKSPACE}")
    print(f"Interval: {interval}s")
    print(f"Log: {LOG_FILE}")
    print("Press Ctrl+C to stop\n")
    
    state = get_file_state()
    save_state(state)
    
    try:
        while True:
            time.sleep(interval)
            new_state = get_file_state()
            changes = diff_states(state, new_state)
            
            for path in changes['added']:
                log_change("ADDED", path)
            for path in changes['modified']:
                log_change("MODIFIED", path)
            for path in changes['deleted']:
                log_change("DELETED", path)
            
            if any(changes.values()):
                save_state(new_state)
            state = new_state
    except KeyboardInterrupt:
        print("\nStopped watching")

def check_once():
    """Check for changes once and exit."""
    old_state = load_state()
    new_state = get_file_state()
    
    if not old_state:
        print(f"First run - indexed {len(new_state)} files")
        save_state(new_state)
        return
    
    changes = diff_states(old_state, new_state)
    
    total = sum(len(v) for v in changes.values())
    if total == 0:
        print("No changes detected")
    else:
        print(f"Changes since last check:")
        for path in changes['added']:
            print(f"  + {path}")
        for path in changes['modified']:
            print(f"  ~ {path}")
        for path in changes['deleted']:
            print(f"  - {path}")
    
    save_state(new_state)

def main():
    if len(sys.argv) > 1:
        if sys.argv[1] == 'watch':
            interval = int(sys.argv[2]) if len(sys.argv) > 2 else 5
            watch(interval)
        elif sys.argv[1] == 'check':
            check_once()
        else:
            print("Usage:")
            print("  watcher.py check    - Check for changes once")
            print("  watcher.py watch [interval]  - Watch continuously")
    else:
        check_once()

if __name__ == "__main__":
    main()
