#!/usr/bin/env bash
set -euo pipefail

CONFIG="${1:-Release}"
RUN_TESTS="${2:-0}"
EXE_NAME="${3:-bio}"

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BUILD="$ROOT/build"
OBJ="$BUILD/obj"
LIB="$BUILD/lib"
BIN="$BUILD/bin"

CC="${CC:-cc}"
AR="${AR:-ar}"

mkdir -p "$OBJ" "$LIB" "$BIN"

INCLUDE="-I$ROOT/include"
STD="-std=c11"
WARN="-Wall -Wextra -Wpedantic"
ARCH="-mavx2 -mpopcnt -mfma"

if [ "$CONFIG" = "Debug" ]; then
  OPT="-O0 -g -DDEBUG $ARCH"
else
  OPT="-O3 -DNDEBUG $ARCH"
fi

SOURCES=(
  src/bio_opcode.c
  src/bio_dispatch.c
  src/bio_handlers.c
  src/bio_lexer.c
  src/bio_context.c
  src/bio_gguf.c
  src/bio_cpuid.c
  src/bio_kernels.c
  src/bio_sparse.c
  src/bio_quant.c
  src/bio_forward.c
  src/bio_bdl.c
  src/bio_state.c
  src/bio_product.c
  src/bio_capi.c
)

OBJS=()
echo "[build] compiling Bio-Digital native sources ..."
for s in "${SOURCES[@]}"; do
  out="$OBJ/$(basename "$s" .c).o"
  $CC -c "$ROOT/$s" -o "$out" $STD $INCLUDE $OPT $WARN
  OBJS+=("$out")
done

LIB_PATH="$LIB/libbio.a"
rm -f "$LIB_PATH"
$AR rcs "$LIB_PATH" "${OBJS[@]}"

EXE_PATH="$BIN/$EXE_NAME"
echo "[build] linking $EXE_NAME ..."
$CC "$ROOT/src/bio_main.c" -o "$EXE_PATH" "$LIB_PATH" $STD $INCLUDE $OPT $WARN

echo "[build] OK"
echo "  exe: $EXE_PATH"
echo "  lib: $LIB_PATH"

if [ "$RUN_TESTS" = "1" ]; then
  mkdir -p "$ROOT/tests/fixtures"

  TEST_OUT="$BIN/bio-tests"
  echo "[test] compiling bio-tests ..."
  $CC "$ROOT/tests/test_lexer.c" -o "$TEST_OUT" "$LIB_PATH" $STD $INCLUDE $OPT $WARN
  "$TEST_OUT"

  MODEL_TEST_OUT="$BIN/bio-model-tests"
  echo "[test] compiling bio-model-tests ..."
  $CC "$ROOT/tests/test_model.c" -o "$MODEL_TEST_OUT" "$LIB_PATH" $STD $INCLUDE $OPT $WARN
  "$MODEL_TEST_OUT"

  GGUF_TEST_OUT="$BIN/bio-gguf-tests"
  GGUF_FIXTURE="$ROOT/tests/fixtures/minimal-q4.gguf"
  echo "[test] compiling bio-gguf-tests ..."
  $CC "$ROOT/tests/test_gguf.c" -o "$GGUF_TEST_OUT" "$LIB_PATH" $STD $INCLUDE $OPT $WARN
  "$GGUF_TEST_OUT" "$GGUF_FIXTURE"

  SPARSE_TEST_OUT="$BIN/bio-sparse-tests"
  echo "[test] compiling bio-sparse-tests ..."
  $CC "$ROOT/tests/test_sparse.c" -o "$SPARSE_TEST_OUT" "$LIB_PATH" $STD $INCLUDE $OPT $WARN
  "$SPARSE_TEST_OUT"

  QUANT_TEST_OUT="$BIN/bio-quant-tests"
  echo "[test] compiling bio-quant-tests ..."
  $CC "$ROOT/tests/test_quant.c" -o "$QUANT_TEST_OUT" "$LIB_PATH" $STD $INCLUDE $OPT $WARN
  "$QUANT_TEST_OUT"

  FORWARD_TEST_OUT="$BIN/bio-forward-tests"
  echo "[test] compiling bio-forward-tests ..."
  $CC "$ROOT/tests/test_forward.c" -o "$FORWARD_TEST_OUT" "$LIB_PATH" $STD $INCLUDE $OPT $WARN
  "$FORWARD_TEST_OUT"

  BDL_TEST_OUT="$BIN/bio-bdl-tests"
  BDL_FIXTURE="$ROOT/tests/fixtures/test.bdl"
  echo "[test] compiling bio-bdl-tests ..."
  $CC "$ROOT/tests/test_bdl.c" -o "$BDL_TEST_OUT" "$LIB_PATH" $STD $INCLUDE $OPT $WARN
  "$BDL_TEST_OUT" "$BDL_FIXTURE"

  STATE_TEST_OUT="$BIN/bio-state-tests"
  STATE_FIXTURE="$ROOT/tests/fixtures/minimal.bdst"
  STATE_DELTA_FIXTURE="$ROOT/tests/fixtures/minimal-state.bdl"
  echo "[test] compiling bio-state-tests ..."
  $CC "$ROOT/tests/test_state.c" -o "$STATE_TEST_OUT" "$LIB_PATH" $STD $INCLUDE $OPT $WARN
  "$STATE_TEST_OUT" "$GGUF_FIXTURE" "$STATE_FIXTURE" "$STATE_DELTA_FIXTURE"

  echo "[test] product CLI ingest/learn/chat ..."
  "$EXE_PATH" ingest "$GGUF_FIXTURE" --out "$STATE_FIXTURE" --delta "$STATE_DELTA_FIXTURE"
  "$EXE_PATH" learn "$STATE_FIXTURE" --seconds 1 --checkpoint-sec 1 --profile nrl-edge --target-steps 1000000
  "$EXE_PATH" chat "$STATE_FIXTURE" --prompt hi --max-tokens 8 --idle-learn-after-sec 1
  printf 'hi\n/stats\n/exit\n' | "$EXE_PATH" serve "$STATE_FIXTURE" --max-tokens 4 --idle-learn-after-sec 1 --checkpoint-sec 1 --profile nrl-edge

  PHASE4_TEST_OUT="$BIN/bio-phase4-tests"
  echo "[test] compiling bio-phase4-tests ..."
  $CC "$ROOT/tests/test_phase4.c" -o "$PHASE4_TEST_OUT" "$LIB_PATH" $STD $INCLUDE $OPT $WARN
  "$PHASE4_TEST_OUT" "$ROOT/examples/phase1_all_opcodes.bio"

  echo "[test] running sample opcode stream ..."
  "$EXE_PATH" run "$ROOT/examples/phase1_all_opcodes.bio"
fi
