#!/bin/sh

# Run every repository check from one reproducible entry point.  CoolProp stays
# outside this checkout: callers must provide its shared library explicitly.

set -eu

fail()
{
    printf 'error: %s\n' "$*" >&2
    exit 1
}

need_command()
{
    command -v "$1" >/dev/null 2>&1 \
        || fail "required command not found: $1"
}

[ -n "${LUACOOLPROP_LIB:-}" ] \
    || fail "LUACOOLPROP_LIB must point to the CoolProp shared library"
case ${LUACOOLPROP_LIB##*/} in
    libCoolProp.dylib|libCoolProp.so|CoolProp.dll) ;;
    *) fail "LUACOOLPROP_LIB must name libCoolProp.dylib, libCoolProp.so, or CoolProp.dll" ;;
esac
[ -f "$LUACOOLPROP_LIB" ] \
    || fail "CoolProp library not found: $LUACOOLPROP_LIB"
[ -r "$LUACOOLPROP_LIB" ] \
    || fail "CoolProp library is not readable: $LUACOOLPROP_LIB"

need_command dirname
need_command awk
need_command lualatex
need_command mkdir
need_command sh
need_command tail
need_command texlua

SCRIPT_DIR=$(CDPATH= cd -P "$(dirname "$0")" && pwd) \
    || fail "could not determine the script directory"
PROJECT_DIR=$(CDPATH= cd -P "$SCRIPT_DIR/.." && pwd) \
    || fail "could not determine the project directory"
LIBRARY_DIR=$(CDPATH= cd -P "$(dirname "$LUACOOLPROP_LIB")" && pwd) \
    || fail "could not resolve LUACOOLPROP_LIB"
LIBRARY_NAME=${LUACOOLPROP_LIB##*/}
LUACOOLPROP_LIB=$LIBRARY_DIR/$LIBRARY_NAME
export LUACOOLPROP_LIB

# Test runners and sandboxes often make the user's TeX tree read-only.  Use a
# temporary cache by default, while preserving any explicit caller choice.
if [ -z "${LUACOOLPROP_TEX_CACHE:-}" ]; then
    LUACOOLPROP_TEX_CACHE=${TMPDIR:-/tmp}/luacoolprop-tex-cache
fi
export LUACOOLPROP_TEX_CACHE

LOG_DIR=$PROJECT_DIR/build-logs
mkdir -p "$LOG_DIR" || fail "could not create $LOG_DIR"

# The syntax pass is intentionally performed by /bin/sh: all project scripts
# must remain portable to the POSIX shell shipped by macOS.
for shell_script in "$SCRIPT_DIR"/*.sh; do
    [ -f "$shell_script" ] || fail "no scripts/*.sh files found"
    if ! sh -n "$shell_script"; then
        fail "shell syntax check failed: ${shell_script##*/}"
    fi
done
printf 'Shell syntax checks passed.\n'

"$SCRIPT_DIR/check-documentation.sh"

run_texlua_test()
{
    test_name=$1
    test_path=$2
    test_log=$LOG_DIR/$test_name.log

    printf 'Testing %s with texlua\n' "$test_path"
    if texlua "$PROJECT_DIR/$test_path" >"$test_log" 2>&1; then
        return 0
    fi

    printf 'error: texlua failed for %s (log: %s)\n' \
        "$test_path" "$test_log" >&2
    tail -n 20 "$test_log" >&2
    return 1
}

run_texlua_test test-luacoolprop tests/test-luacoolprop.lua
run_texlua_test test-pgfplots-autonode tests/test-pgfplots-autonode.lua

# A missing lifecycle hook used to discard every registered label silently.
# Compile the deliberate misuse fixture and require one concise diagnostic,
# rather than allowing either silence or one warning per label.
missing_hook_dir=$LOG_DIR/autonode-missing-hook
missing_hook_console=$missing_hook_dir/console.log
mkdir -p "$missing_hook_dir" \
    || fail "could not create $missing_hook_dir"
printf 'Testing missing autonode lifecycle diagnostic with lualatex\n'
if TEXMFCACHE=$LUACOOLPROP_TEX_CACHE \
    lualatex --shell-escape --interaction=nonstopmode --halt-on-error \
    --file-line-error --output-directory="$missing_hook_dir" \
    "$PROJECT_DIR/tests/tds/autonode-missing-hook.tex" \
    >"$missing_hook_console" 2>&1; then
    :
else
    printf 'error: missing-hook diagnostic fixture failed (log: %s)\n' \
        "$missing_hook_console" >&2
    tail -n 20 "$missing_hook_console" >&2
    exit 1
fi
missing_hook_count=$(awk '
  /label registered without/ { count++ }
  END { print count + 0 }
' "$missing_hook_console")
[ "$missing_hook_count" -eq 1 ] \
    || fail "missing autonode lifecycle must emit exactly one warning (got $missing_hook_count)"

# A narrow visible path must receive a valid label, while a fully invisible
# path must never produce a fallback label outside the fixed axis window.
viewport_dir=$LOG_DIR/autonode-viewport
viewport_console=$viewport_dir/console.log
mkdir -p "$viewport_dir" \
    || fail "could not create $viewport_dir"
printf 'Testing autonode hard axis-border constraint with lualatex\n'
if TEXMFCACHE=$LUACOOLPROP_TEX_CACHE \
    lualatex --shell-escape --interaction=nonstopmode --halt-on-error \
    --file-line-error --output-directory="$viewport_dir" \
    "$PROJECT_DIR/tests/tds/autonode-viewport.tex" \
    >"$viewport_console" 2>&1; then
    :
else
    printf 'error: autonode viewport fixture failed (log: %s)\n' \
        "$viewport_console" >&2
    tail -n 20 "$viewport_console" >&2
    exit 1
fi
awk '
  /final status: overlaps=0 outside=0 hidden=1/ { status = 1 }
  /final label #1: pos=/ { crossing = 1 }
  /final label #2: pos=/ { inside = 1 }
  /final label #3: hidden/ { hidden = 1 }
  END { exit !(status && crossing && inside && hidden) }
' "$viewport_console" \
    || fail "autonode viewport sampling or hard border check failed (log: $viewport_console)"

geometry_dir=$LOG_DIR/autonode-node-geometry
geometry_console=$geometry_dir/console.log
mkdir -p "$geometry_dir" \
    || fail "could not create $geometry_dir"
printf 'Testing measured autonode node geometry with lualatex\n'
if TEXMFCACHE=$LUACOOLPROP_TEX_CACHE \
    lualatex --shell-escape --interaction=nonstopmode --halt-on-error \
    --file-line-error --output-directory="$geometry_dir" \
    "$PROJECT_DIR/tests/tds/autonode-node-geometry.tex" \
    >"$geometry_console" 2>&1; then
    :
else
    printf 'error: autonode geometry fixture failed (log: %s)\n' \
        "$geometry_console" >&2
    tail -n 20 "$geometry_console" >&2
    exit 1
fi
awk '
  /final status: overlaps=0 outside=0 hidden=0/ { status = 1 }
  /final label #1: pos=/ { first = 1 }
  /final label #2: pos=/ { second = 1 }
  END { exit !(status && first && second) }
' "$geometry_console" \
    || fail "autonode measured geometry fixture failed (log: $geometry_console)"

# Consecutive axes must each start with a fresh Lua label registry. PGFPlots may
# execute its begin-axis hook before the autonode key is parsed; this fixture
# catches a stale label count leaking from the first axis into the second.
multi_axis_dir=$LOG_DIR/autonode-multi-axis
multi_axis_console=$multi_axis_dir/console.log
mkdir -p "$multi_axis_dir" \
    || fail "could not create $multi_axis_dir"
printf 'Testing autonode state reset across consecutive axes with lualatex\n'
if TEXMFCACHE=$LUACOOLPROP_TEX_CACHE \
    lualatex --shell-escape --interaction=nonstopmode --halt-on-error \
    --file-line-error --output-directory="$multi_axis_dir" \
    "$PROJECT_DIR/tests/tds/autonode-multi-axis.tex" \
    >"$multi_axis_console" 2>&1; then
    :
else
    printf 'error: autonode multi-axis fixture failed (log: %s)\n' \
        "$multi_axis_console" >&2
    tail -n 20 "$multi_axis_console" >&2
    exit 1
fi
awk '
  /final status: overlaps=0 outside=0 hidden=0/ { status++ }
  /final label #1: pos=/ { first++ }
  /final label #2:/ { stale++ }
  END { exit !(status == 2 && first == 2 && stale == 0) }
' "$multi_axis_console" \
    || fail "autonode did not reset between axes (log: $multi_axis_console)"

# This final step exercises LaTeX, plain TeX, and ConTeXt, regenerates all
# shipped examples and the indexed manual, and rejects TeX warnings.
"$SCRIPT_DIR/build-examples.sh"

printf 'All LuaCoolProp tests passed.\n'
