"""Server version resolution.

Production Docker images install the wheel and ``importlib.metadata`` is the
truth. Editable dev installs (``pip install -e packages/server``) record the
version at install time and *don't auto-refresh* when the source ``pyproject.toml``
bumps — so a developer that bumped from 0.3.x to 0.7.x without reinstalling
will keep reporting 0.3.x via ``importlib.metadata``.

To make the running app match the source tree without forcing a reinstall,
we read both and return the higher of the two. The dist-info wins in prod
(no pyproject alongside), the source wins in dev when the editable install is
stale.
"""

from __future__ import annotations

import logging
from importlib.metadata import PackageNotFoundError, version as _pkg_version
from pathlib import Path

_LOGGER = logging.getLogger(__name__)

_PACKAGE_NAME = "notify-bridge-server"
_UNKNOWN = "0.0.0+unknown"


def _read_source_version() -> str | None:
    """Best-effort read of the source ``pyproject.toml`` version.

    Returns ``None`` when the file isn't reachable (the normal prod case),
    so callers fall back to the installed metadata.
    """
    # Module is at packages/server/src/notify_bridge_server/version.py,
    # pyproject sits at packages/server/pyproject.toml — three parents up.
    pyproject = Path(__file__).resolve().parents[2] / "pyproject.toml"
    if not pyproject.is_file():
        return None
    try:
        import tomllib  # Python 3.11+ stdlib — server requires 3.12.

        data = tomllib.loads(pyproject.read_text(encoding="utf-8"))
        version = data.get("project", {}).get("version")
        return str(version) if version else None
    except (OSError, ValueError) as err:  # pragma: no cover — defensive
        _LOGGER.debug("Could not read source pyproject version: %s", err)
        return None


def _segments(version: str) -> tuple[int, ...]:
    """Best-effort tuple-of-ints for ordering. Suffixes (``-rc1``) are stripped."""
    if not version:
        return ()
    head = version.split("+", 1)[0].split("-", 1)[0]
    out: list[int] = []
    for piece in head.split("."):
        digits = "".join(c for c in piece if c.isdigit())
        if digits:
            out.append(int(digits))
    return tuple(out)


def resolve_version() -> str:
    """Return the version the running server should advertise.

    Prefers the highest of (installed metadata, source pyproject) so an
    out-of-date editable install never lies to the UI. In production builds
    only the installed metadata is available, which is correct by definition.
    """
    try:
        installed: str | None = _pkg_version(_PACKAGE_NAME)
    except PackageNotFoundError:
        installed = None
    source = _read_source_version()

    candidates = [v for v in (installed, source) if v]
    if not candidates:
        return _UNKNOWN
    if len(candidates) == 1:
        return candidates[0]
    # Two candidates — return the higher by numeric segments. Ties: prefer
    # source, since that's what the developer just edited.
    a, b = candidates
    return a if _segments(a) > _segments(b) else b
