"""
neurocli watch — file watcher with live AI feedback on save
"""
import time
import threading
from pathlib import Path
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

SKIP_DIRS = {".git", "node_modules", "__pycache__", ".venv", "venv", "dist", "build"}
WATCH_EXTENSIONS = {".py", ".js", ".ts", ".jsx", ".tsx", ".go", ".rs", ".java", ".c", ".cpp", ".rb", ".php"}

_last_event_time = {}
DEBOUNCE_SECONDS = 1.5


class NeuroCLIWatchHandler(FileSystemEventHandler):
    def __init__(self, on_change, cfg, session_id, project, cwd):
        self.on_change = on_change
        self.cfg = cfg
        self.session_id = session_id
        self.project = project
        self.cwd = cwd
        self._lock = threading.Lock()

    def on_modified(self, event):
        if event.is_directory:
            return
        path = event.src_path
        ext = Path(path).suffix
        if ext not in WATCH_EXTENSIONS:
            return
        if any(skip in path for skip in SKIP_DIRS):
            return

        now = time.time()
        with self._lock:
            last = _last_event_time.get(path, 0)
            if now - last < DEBOUNCE_SECONDS:
                return
            _last_event_time[path] = now

        # Run in thread to avoid blocking watchdog
        threading.Thread(
            target=self.on_change,
            args=(path, self.cfg, self.session_id, self.project, self.cwd),
            daemon=True
        ).start()


def start_watch(directory: str, on_change, cfg: dict, session_id: int, project: str, cwd: str):
    """Start watching a directory. Blocks until KeyboardInterrupt."""
    handler = NeuroCLIWatchHandler(on_change, cfg, session_id, project, cwd)
    observer = Observer()
    observer.schedule(handler, path=directory, recursive=True)
    observer.start()
    return observer


def make_watch_callback(agent_run_fn, tui):
    """Factory to create the on_change callback."""
    def on_change(path: str, cfg, session_id, project, cwd):
        try:
            content = Path(path).read_text(errors="replace")
        except Exception:
            return

        tui.console.print(f"\n[bright_yellow]◉ WATCH:[/] [bright_cyan]{path}[/] changed")

        prompt = f"""Review this file that was just saved. 
File: {path}
Content:
```
{content[:3000]}
```

Give a quick code review: bugs, issues, improvements. Be concise (3-5 bullet points max). 
If the code looks fine, just say "✓ Looks good."
"""
        result = agent_run_fn(
            user_input=prompt,
            messages=[],
            cfg=cfg,
            session_id=session_id,
            project=project,
            cwd=cwd,
            dry_run=True,  # watch mode never writes
            on_text=None,
            on_tool_start=None,
            on_tool_result=None,
        )
        if result.get("text"):
            tui.console.print(f"[grey50]  ↳ watch review:[/]")
            tui.console.print(result["text"])

    return on_change
