"""Public entry point for the fine-tuning pipeline. training_tasks.py should only
import from here, never reach into mlx_backend/cuda_backend directly — get_backend()
picks the right one for this machine's hardware.
"""

from types import ModuleType

from app.services.finetune import cuda_backend, mlx_backend
from app.services.finetune.detect import Backend, detect_backend
from app.services.finetune.shared import (
    MIN_APPROVED_EXAMPLES,
    FineTuneError,
    ensure_base_model_downloaded,
    export_training_data,
    import_into_ollama,
    job_dir,
    run_gguf_convert,
)

__all__ = [
    "MIN_APPROVED_EXAMPLES",
    "FineTuneError",
    "Backend",
    "detect_backend",
    "get_backend",
    "ensure_base_model_downloaded",
    "export_training_data",
    "import_into_ollama",
    "job_dir",
    "run_gguf_convert",
]

_BACKENDS: dict[str, ModuleType] = {"mlx": mlx_backend, "cuda": cuda_backend}


def get_backend() -> ModuleType:
    """The backend module for *this* machine — exposes run_lora_training(...),
    run_fuse(...), and parse_progress_line(...) with identical signatures regardless
    of which one it is (duck-typed, not an ABC — every other backend-ish thing in this
    codebase, e.g. Ollama vs a future provider, follows the same plain-module pattern)."""
    backend = detect_backend()
    module = _BACKENDS.get(backend)
    if module is None:
        raise FineTuneError(
            "Fine-tuning isn't available on this machine — it needs either Apple "
            "Silicon (MLX) or an NVIDIA GPU (CUDA). Neither was detected."
        )
    return module
