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

build_root=$1
entry_src=$2
entry_both_src=$3
lib1_src=$4
lib2_src=$5

cli_dir="$build_root/src/cli"
php2ast="$cli_dir/phpefc-php2ast"
phpast2phpir="$cli_dir/phpefc-phpast2phpir"
phpir2valair="$cli_dir/phpefc-phpir2valair"
valair2vala="$cli_dir/phpefc-valair2vala"
valair_optimize="$cli_dir/phpefc-valair-optimize-typing"

source_prefix() {
    python3 - "$1" <<'PY'
import re, sys
path = sys.argv[1].replace('\\', '/')
path = path.rsplit('/', 1)[-1]
part = re.sub(r'[^A-Za-z0-9_]+', '_', path).strip('_') or 'unknown_php'
if not re.match(r'^[A-Za-z_]', part):
    part = '_' + part
print(part)
PY
}

work=${MESON_TEST_TMPDIR:-}
if [ -z "$work" ]; then
    work=$(mktemp -d)
    trap 'rm -rf "$work"' EXIT
fi
mkdir -p "$work"

lib1_prefix=$(source_prefix "$(realpath "$lib1_src")")
lib2_prefix=$(source_prefix "$(realpath "$lib2_src")")
lib1_func="phpef_${lib1_prefix}__duplicate_func"
lib2_func="phpef_${lib2_prefix}__duplicate_func"

make_ast_ir() {
    local src=$1 base=$2
    "$php2ast" "$src" "$work/$base.phpast" >/dev/null
}

make_ast_ir "$entry_src" entry
make_ast_ir "$entry_both_src" entry_both
make_ast_ir "$lib1_src" duplicate_lib1
make_ast_ir "$lib2_src" duplicate_lib2

"$phpast2phpir" "$work/entry.phpast" "$work/entry.phpir" \
    --external-phpast "$work/duplicate_lib1.phpast" \
    --external-phpast "$work/duplicate_lib2.phpast" >/dev/null
"$phpast2phpir" "$work/entry_both.phpast" "$work/entry_both.phpir" \
    --external-phpast "$work/duplicate_lib1.phpast" \
    --external-phpast "$work/duplicate_lib2.phpast" >/dev/null
"$phpast2phpir" "$work/duplicate_lib1.phpast" "$work/duplicate_lib1.phpir" >/dev/null
"$phpast2phpir" "$work/duplicate_lib2.phpast" "$work/duplicate_lib2.phpir" >/dev/null

"$phpir2valair" "$work/entry.phpir" "$work/entry.valair" \
    --external-phpir "$work/duplicate_lib1.phpir" \
    --external-phpir "$work/duplicate_lib2.phpir" >/dev/null
"$phpir2valair" "$work/duplicate_lib1.phpir" "$work/duplicate_lib1.valair" >/dev/null
"$phpir2valair" "$work/duplicate_lib2.phpir" "$work/duplicate_lib2.valair" >/dev/null
"$valair_optimize" "$work/entry.valair" "$work/entry.valair.afteropt.typing-zval2static" >/dev/null
"$valair_optimize" "$work/duplicate_lib1.valair" "$work/duplicate_lib1.valair.afteropt.typing-zval2static" >/dev/null
"$valair_optimize" "$work/duplicate_lib2.valair" "$work/duplicate_lib2.valair.afteropt.typing-zval2static" >/dev/null
"$valair2vala" "$work/entry.valair.afteropt.typing-zval2static" "$work/entry.vala" >/dev/null
"$valair2vala" "$work/duplicate_lib1.valair.afteropt.typing-zval2static" "$work/duplicate_lib1.vala" --no-main >/dev/null
"$valair2vala" "$work/duplicate_lib2.valair.afteropt.typing-zval2static" "$work/duplicate_lib2.vala" --no-main >/dev/null

if ! grep -Fq 'PhpefRuntimeCore.call_function("duplicate_func",' "$work/entry.vala"; then
    echo 'entry did not call included user function through runtime registry by PHP name' >&2
    cat "$work/entry.vala" >&2
    exit 1
fi
if ! grep -Fq "public static Zval ${lib1_func}(Zval[] args)" "$work/duplicate_lib1.vala"; then
    echo 'lib1 support function was not source-path-prefixed' >&2
    cat "$work/duplicate_lib1.vala" >&2
    exit 1
fi
if ! grep -Fq "public static Zval ${lib2_func}(Zval[] args)" "$work/duplicate_lib2.vala"; then
    echo 'lib2 support function was not source-path-prefixed' >&2
    cat "$work/duplicate_lib2.vala" >&2
    exit 1
fi

set +e
"$phpir2valair" "$work/entry_both.phpir" "$work/entry_both.valair" \
    --external-phpir "$work/duplicate_lib1.phpir" \
    --external-phpir "$work/duplicate_lib2.phpir" >"$work/both.out" 2>"$work/both.err"
rc=$?
set -e
if [ "$rc" -eq 0 ]; then
    echo 'including both duplicate function libs unexpectedly succeeded' >&2
    exit 1
fi
if ! grep -Fq 'Duplicate PHP function declaration reachable through includes: duplicate_func' "$work/both.err"; then
    echo 'expected duplicate reachable function diagnostic' >&2
    cat "$work/both.err" >&2
    exit 1
fi

printf 'ok 1 - duplicate support-file functions are source-path-prefixed unless both are included\n'
