#!/usr/bin/env bash
# Pack mega.tsv → mega.bin · generate limb table · link h7-recheck (in-process · fast re)
#   ./Build/h7-pack-and-link.sh
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
FAST="$ROOT/out/h7fast"
OBJD="$FAST/obj"
TSV="$FAST/mega.tsv"
BIN="$FAST/mega.bin"
MAP="$FAST/limb_index.txt"
TABLE="$ROOT/Build/h7_recheck_table.c"
OUTBIN="$ROOT/Build/h7-recheck"

[[ -f "$TSV" ]] || { echo "need $TSV"; exit 2; }
mkdir -p "$FAST" "$OBJD"

# limb index: unique limbs from TSV that have .o
cut -f3 "$TSV" | LC_ALL=C sort -u >"$FAST/limbs_in_tsv.txt"
: >"$MAP"
idx=0
objs=()
while IFS= read -r limb; do
  [[ -z "$limb" ]] && continue
  obj="$OBJD/$limb.o"
  if [[ ! -f "$obj" ]]; then
    src="$ROOT/$limb/x86_64.asm"
    [[ -f "$src" ]] || continue
    nasm -f elf64 -o "$obj" "$src" 2>/dev/null || continue
  fi
  sym=$(grep -m1 -E '^\s*global\s+\w+' "$ROOT/$limb/x86_64.asm" 2>/dev/null | awk '{print $2}' || true)
  [[ -n "$sym" && "$sym" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]] || continue
  printf '%s\t%s\t%s\n' "$idx" "$limb" "$sym" >>"$MAP"
  objs+=("$obj")
  idx=$((idx + 1))
done <"$FAST/limbs_in_tsv.txt"
nlimbs=$idx
echo "limbs_indexed=$nlimbs"

# generate C table
{
  echo '/* auto-generated · do not edit */'
  echo '#include <stdint.h>'
  echo 'typedef int32_t (*limb_fn)(int32_t,int32_t,int32_t);'
  echo 'typedef struct { const char *name; limb_fn fn; } LimbEnt;'
  while IFS=$'\t' read -r i limb sym; do
    echo "extern int32_t ${sym}(int32_t,int32_t,int32_t);"
  done <"$MAP"
  echo 'const LimbEnt h7_limbs[] = {'
  while IFS=$'\t' read -r i limb sym; do
    echo "  {\"$limb\", (limb_fn)${sym}},"
  done <"$MAP"
  echo '};'
  echo "const int h7_nlimbs = $nlimbs;"
} >"$TABLE"

# pack TSV → binary
python3 - "$TSV" "$BIN" "$MAP" <<'PY'
import struct, sys
tsv, binpath, mappath = sys.argv[1], sys.argv[2], sys.argv[3]
idx = {}
for line in open(mappath):
    parts = line.rstrip('\n').split('\t')
    if len(parts) >= 2:
        idx[parts[1]] = int(parts[0])
recs = []
skip = 0
for line in open(tsv):
    p = line.rstrip('\n').split('\t')
    if len(p) < 7:
        skip += 1
        continue
    id_, track, limb, a, b, c, want = p[0], p[1], p[2], p[3], p[4], p[5], p[6]
    if limb not in idx:
        skip += 1
        continue
    try:
        recs.append(struct.pack('<IHiiiixx', int(id_), idx[limb], int(a), int(b), int(c), int(want)))
    except Exception:
        skip += 1
open(binpath, 'wb').write(b''.join(recs))
print(f'packed N={len(recs)} skip={skip} → {binpath}')
PY

# link recheck with all limb objects (no-pie for simple)
cc -O2 -no-pie -o "$OUTBIN" "$ROOT/Build/h7-recheck.c" "$TABLE" "${objs[@]}" 2>"$FAST/recheck_link.err" || {
  echo "link failed · see $FAST/recheck_link.err"
  tail -20 "$FAST/recheck_link.err"
  exit 1
}
echo "OK $OUTBIN + $BIN"
"$OUTBIN" "$BIN" "$FAST/fails_smoke" 2>&1 | head -3
rm -rf "$FAST/fails_smoke"
