"""
Inject a SOURCE-DERIVED build id: -DPDL_BUILD_ID="<12 hex chars>"

WHY NOT __DATE__/__TIME__
-------------------------
The first attempt at build identity used __DATE__ " " __TIME__. That captures
COMPILE time, and every PlatformIO environment compiles separately — so a
six-unit deploy from one unchanged source tree produced six different stamps:

    Spencer02  'Aug  2 2026 16:56:55'
    Gateway01  'Aug  2 2026 17:01:17'
    Spencer01  'Aug  2 2026 17:03:13'
    ...

The whole point of the stamp is to answer "are these units running the same
code?", and that version answered "no" every time, guaranteeing a permanent
false-positive on the fleet divergence alert.

Hashing the source tree fixes it: identical source -> identical id on every
board and every environment, regardless of when each was compiled. Different
source -> different id. That is the property actually needed.

Per-device identity (name, sensor id) is deliberately NOT part of the hash —
those differ legitimately between units and must not make two otherwise
identical builds look divergent.
"""
import hashlib
import os

Import("env")  # noqa: F821  (injected by PlatformIO)

PROJECT_DIR = env["PROJECT_DIR"]  # noqa: F821


def _iter_source_files():
    """Everything that can change behaviour: src/, lib/, and the build config."""
    roots = [os.path.join(PROJECT_DIR, "src"), os.path.join(PROJECT_DIR, "lib")]
    exts = (".c", ".cpp", ".h", ".hpp", ".cc")
    for root in roots:
        if not os.path.isdir(root):
            continue
        for dirpath, _dirnames, filenames in os.walk(root):
            for fn in sorted(filenames):
                if fn.endswith(exts):
                    yield os.path.join(dirpath, fn)
    ini = os.path.join(PROJECT_DIR, "platformio.ini")
    if os.path.isfile(ini):
        yield ini


def compute_build_id():
    h = hashlib.sha256()
    for path in sorted(_iter_source_files()):
        # Hash the path (relative, normalised) so adding/removing/renaming a
        # file changes the id even if total content bytes happen to match.
        rel = os.path.relpath(path, PROJECT_DIR).replace("\\", "/")
        h.update(rel.encode("utf-8"))
        try:
            with open(path, "rb") as f:
                h.update(f.read())
        except OSError:
            # Unreadable file still contributes its path, so the id changes
            # rather than silently pretending nothing happened.
            h.update(b"<unreadable>")
    return h.hexdigest()[:12]


build_id = compute_build_id()
env.Append(CPPDEFINES=[("PDL_BUILD_ID", env.StringifyMacro(build_id))])  # noqa: F821
print(f"[build_id] source hash = {build_id}")
