"""Python package wrapper for the C++ Cogniflow pipeline engine."""

from __future__ import annotations

from importlib import metadata
import os
from pathlib import Path
import shutil

__version__ = "0.1.4"


def _locate_distribution_file(*relative_candidates: str) -> Path:
    distribution = metadata.distribution("cf-pipeline-engine")
    files = distribution.files or []
    for candidate in relative_candidates:
        for entry in files:
            if entry.as_posix() == candidate:
                return Path(distribution.locate_file(entry)).resolve()
    raise FileNotFoundError(
        f"Could not locate any of {relative_candidates!r} in cf-pipeline-engine distribution files."
    )


def cf_pipeline_v2_path() -> str:
    return str(_locate_distribution_file("bin/cf_pipeline_v2.exe", "bin/cf_pipeline_v2"))


def cf_siggen_path() -> str:
    return str(_locate_distribution_file("bin/cf_siggen.exe", "bin/cf_siggen"))


def cf_engine_include_path() -> str:
    return str(_locate_distribution_file("include/cf_step_abi.h").parent)


def cf_type_registry_path() -> str:
    return str(_locate_distribution_file("bin/type_registry.v0.json"))


def _repo_build_engine_exe() -> str | None:
    engine_dirs = [
        Path("sandcastle/cf_pipeline/cf_pipeline_engine"),
        Path(__file__).resolve().parents[1],
    ]

    seen: set[str] = set()
    ordered_dirs: list[Path] = []
    for entry in engine_dirs:
        key = str(entry)
        if key in seen:
            continue
        seen.add(key)
        ordered_dirs.append(entry)

    config_dirs = ["Release", "RelWithDebInfo", "Debug", "MinSizeRel"]
    exe_names = ["cf_pipeline_v2.exe", "cf_pipeline_v2"]

    candidates: list[Path] = []
    for engine_dir in ordered_dirs:
        build_dir = engine_dir / "build"
        for exe_name in exe_names:
            candidates.append(build_dir / exe_name)
        for config_dir in config_dirs:
            for exe_name in exe_names:
                candidates.append(build_dir / config_dir / exe_name)
                candidates.append(build_dir / "bin" / config_dir / exe_name)

    for exe_name in exe_names:
        candidates.append(Path(exe_name))

    for candidate in candidates:
        if candidate.exists():
            return str(candidate)
    return None


def resolve_cf_pipeline_v2_executable() -> str:
    env_override = os.environ.get("CF_PIPELINE_V2_EXE")
    if env_override:
        return env_override

    try:
        return cf_pipeline_v2_path()
    except Exception:
        pass

    on_path = shutil.which("cf_pipeline_v2") or shutil.which("cf_pipeline_v2.exe")
    if on_path:
        return on_path

    repo_build = _repo_build_engine_exe()
    if repo_build:
        return repo_build

    return "cf_pipeline_v2"


__all__ = [
    "__version__",
    "cf_pipeline_v2_path",
    "cf_siggen_path",
    "cf_engine_include_path",
    "cf_type_registry_path",
    "resolve_cf_pipeline_v2_executable",
]
