"""Helpers for locating the active quickstart source tree for Alembic."""

from __future__ import annotations

from pathlib import Path
from typing import MutableSequence, Sequence


_PACKAGE_DIRNAME = "spaps_server_quickstart"


def _dedupe_paths(raw_paths: Sequence[str | Path]) -> list[Path]:
    """Normalize candidate paths while preserving first-seen order."""
    seen: set[str] = set()
    candidates: list[Path] = []
    for raw_path in raw_paths:
        if not raw_path:
            continue
        path = Path(raw_path).resolve()
        normalized = str(path)
        if normalized in seen:
            continue
        seen.add(normalized)
        candidates.append(path)
    return candidates


def resolve_quickstart_src_path(
    alembic_env_path: str | Path,
    sys_path: Sequence[str],
) -> str | None:
    """Return the best source root that contains the quickstart package.

    Preference order:
    1. Existing `sys.path` entries that already expose the package. This keeps
       Docker bind mounts like `/app/src` ahead of any packaged fallback.
    2. Known fallback roots relative to `alembic/env.py`.
    """

    alembic_dir = Path(alembic_env_path).resolve().parent
    fallback_paths = [
        Path("/app/src"),
        alembic_dir.parent / "packages" / "python-server-quickstart" / "src",
    ]

    for candidate in _dedupe_paths([*sys_path, *fallback_paths]):
        if (candidate / _PACKAGE_DIRNAME).exists():
            return str(candidate)

    return None


def ensure_quickstart_src_path(
    alembic_env_path: str | Path,
    sys_path: MutableSequence[str],
) -> str | None:
    """Move the resolved quickstart source root to the front of sys.path."""

    resolved = resolve_quickstart_src_path(alembic_env_path, list(sys_path))
    if resolved is None:
        return None

    resolved_path = Path(resolved).resolve()
    filtered = [
        entry
        for entry in sys_path
        if not entry or Path(entry).resolve() != resolved_path
    ]
    sys_path[:] = filtered
    sys_path.insert(0, resolved)
    return resolved
