from __future__ import annotations

import logging
import time
from pathlib import Path

from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer

from companion.config import load_config
from companion.rag.indexer import Indexer
from companion.rag.vector_store import VectorStore

logger = logging.getLogger(__name__)


class VaultEventHandler(FileSystemEventHandler):
    """Handles file system events in the vault directory and triggers indexing."""

    def __init__(self, indexer: Indexer, debounce_seconds: float = 5.0):
        self.indexer = indexer
        self.debounce_seconds = debounce_seconds
        self._last_sync: dict[str, float] = {}

    def on_any_event(self, event):
        """Process a file system event and debounce per file path."""
        if event.is_directory:
            return
        if not event.src_path.endswith(".md"):
            return
        path = event.src_path
        now = time.time()
        if now - self._last_sync.get(path, 0) < self.debounce_seconds:
            return
        self._last_sync[path] = now
        try:
            self.indexer.sync()
        except (OSError, RuntimeError) as exc:
            logger.error("Sync failed: %s", exc)


def start_watcher(config_path: str = "config.json") -> None:
    """Load configuration and start watching the vault directory for changes."""
    config = load_config(config_path)
    vault_path = Path(config.vault.path)
    if not vault_path.exists():
        raise FileNotFoundError(f"Vault path does not exist: {vault_path}")
    store = VectorStore(
        uri=config.rag.vector_store.path, dimensions=config.rag.embedding.dimensions
    )
    indexer = Indexer(config, store)
    handler = VaultEventHandler(indexer)
    observer = Observer()
    observer.schedule(handler, str(vault_path), recursive=True)
    observer.start()
    logger.info("Watching %s for changes...", vault_path)
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()


if __name__ == "__main__":
    start_watcher()
