#!/usr/bin/env python3
"""
cache.py - Global GGUF Scanner Cache

WO-TOKENIZER-BRIDGE-01.1: Provides a module-level cache for GGUFScanner instances.

This eliminates the repeated "Scanning: ..." output when multiple components
(MistralTokenizerBridge, TensorAccessor, etc.) need to access the same GGUF file.

Usage:
    from helix_cdc.gguf.cache import get_scanner, clear_scanner_cache

    # First call scans the file
    scanner = get_scanner("model.gguf")

    # Subsequent calls return cached instance (no scanning)
    scanner2 = get_scanner("model.gguf")
    assert scanner is scanner2

    # Clear cache when done
    clear_scanner_cache()
"""

from __future__ import annotations

import io
import sys
from pathlib import Path
from typing import Dict, Union

from helix_cdc.gguf.scanner import GGUFScanner


# Module-level cache: absolute path -> scanned GGUFScanner instance
_SCANNER_CACHE: Dict[str, GGUFScanner] = {}


def get_scanner(
    gguf_path: Union[str, Path],
    quiet: bool = True,
) -> GGUFScanner:
    """
    Get or create a cached GGUFScanner for a GGUF file.

    On first access for a path, scans the file and caches the result.
    Subsequent accesses return the cached scanner (no re-scanning).

    Args:
        gguf_path: Path to the GGUF file.
        quiet: If True (default), suppress print output during scanning.

    Returns:
        Scanned GGUFScanner instance.
    """
    key = str(Path(gguf_path).absolute())

    if key not in _SCANNER_CACHE:
        scanner = GGUFScanner(gguf_path)

        if quiet:
            # Suppress scan output
            old_stdout = sys.stdout
            sys.stdout = io.StringIO()
            try:
                scanner.scan()
            finally:
                sys.stdout = old_stdout
        else:
            scanner.scan()

        _SCANNER_CACHE[key] = scanner

    return _SCANNER_CACHE[key]


def clear_scanner_cache() -> None:
    """Clear all cached GGUFScanner instances."""
    _SCANNER_CACHE.clear()


def get_cache_info() -> Dict[str, int]:
    """
    Get information about the scanner cache.

    Returns:
        Dict with cache stats.
    """
    return {
        "num_cached_scanners": len(_SCANNER_CACHE),
        "cached_paths": list(_SCANNER_CACHE.keys()),
    }
