"""
Store management for CodeContext - handles project stores lifecycle.

This module manages the lazy loading and caching of ContextStore instances.
The embedder must be initialized before get_store() is called.
"""

from typing import Dict, List, Optional

from ..memory_store import ContextStore
from ..cli_utils import PROJECTS_DIR, encode_project_path


# Default project name
DEFAULT_PROJECT = "default"
ALL_PROJECTS = "__all__"  # Special value for "All Projects" view

# Global state - stores dictionary (initialized lazily)
stores: Dict[str, ContextStore] = {}

# These will be set by server.py during startup
_embedder = None
_device = "cpu"


def set_embedder(embedder, device: str = "cpu"):
    """Set the shared embedder instance (called once at server startup)."""
    global _embedder, _device
    _embedder = embedder
    _device = device


def get_store(project: str) -> ContextStore:
    """Get or create a store for the given project (lazy loading).

    The project parameter can be:
    - A full path like "C:\\Users\\Sam\\my-app" (gets encoded)
    - An already-encoded name like "C--Users-Sam-my-app"
    - A simple name like "agentic-coder" (used as-is for backward compat)

    Returns:
        ContextStore instance for the project

    Raises:
        RuntimeError: If embedder hasn't been initialized via set_embedder()
    """
    global stores

    if _embedder is None:
        raise RuntimeError("Embedder not initialized. Call set_embedder() first.")

    if not project:
        project = DEFAULT_PROJECT

    # Encode the project path if it looks like a full path
    # (contains path separators or drive letter)
    if "\\" in project or "/" in project or (len(project) > 1 and project[1] == ":"):
        encoded_name = encode_project_path(project)
    else:
        # Already a simple/encoded name, use as-is
        encoded_name = project

    if encoded_name not in stores:
        # Use encoded name for directory path
        db_path = PROJECTS_DIR / encoded_name / "vector_db"
        stores[encoded_name] = ContextStore(
            db_path=str(db_path),
            embedder=_embedder,
            device=_device,
            project_name=encoded_name
        )
        print(f"[Server] Created store for project: {encoded_name}")

    return stores[encoded_name]


def list_projects() -> List[str]:
    """List all projects with databases (excludes special ALL_PROJECTS value).

    Scans ~/.codecontext/projects/ for project directories.
    Returns encoded project names (e.g., "C--Users-Sam-my-app").
    """
    PROJECTS_DIR.mkdir(parents=True, exist_ok=True)
    projects = []
    for d in PROJECTS_DIR.iterdir():
        # Skip the special ALL_PROJECTS folder if it was accidentally created
        if d.name == ALL_PROJECTS:
            continue
        # lancedb is inside vector_db subfolder
        if d.is_dir() and (d / "vector_db" / "lancedb").exists():
            projects.append(d.name)
    return sorted(projects)


def get_all_stores() -> List[ContextStore]:
    """Get stores for all projects."""
    return [get_store(p) for p in list_projects()]
