# /// script
# requires-python = ">=3.11"
# dependencies = []
# ///
"""
Byte-level comparison of the four Garmin FIT files for "One activity, four FIT files".

    uv run static/files/garmin-fit/fit_bytes.py

Prints size, SHA-256 and the FIT file header of each file. No FIT parsing needed:
the header is the first 12 or 14 bytes and its layout is fixed by the FIT protocol.
"""

import hashlib
import struct
from pathlib import Path

HERE = Path(__file__).parent
FILES = {
    "Watch (USB)": HERE / "garmin_device_usb.fit",
    "Account export": HERE / "garmin_gdpr_dump.fit",
    "Export Original": HERE / "garmin_connect_web.fit",
    "Connect API": HERE / "garmin_connect_api.fit",
}


def header(data: bytes) -> dict:
    size, protocol, profile, data_size, signature = struct.unpack("<BBHI4s", data[:12])
    assert signature == b".FIT", "not a FIT file"
    return {
        "protocol": f"{protocol >> 4}.{protocol & 0x0F}",
        "profile": f"{profile // 1000}.{profile % 1000}",
        "data bytes": data_size,
    }


rows = []
for name, path in FILES.items():
    data = path.read_bytes()
    rows.append({
        "file": name,
        "bytes": len(data),
        "sha256": hashlib.sha256(data).hexdigest()[:12],
        **header(data),
    })

columns = list(rows[0])
print("| " + " | ".join(columns) + " |")
print("|" + "---|" * len(columns))
for row in rows:
    print("| " + " | ".join(str(row[c]) for c in columns) + " |")

watch = FILES["Watch (USB)"].read_bytes()
print()
for name, path in list(FILES.items())[1:]:
    print(f"{name} is byte-identical to the watch's file: {path.read_bytes() == watch}")
