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

root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)
installer="${root}/dependencies/auto_install.sh"
tmp_root=$(mktemp -d)
trap 'rm -rf "${tmp_root}"' EXIT

fail()
{
  echo "FAIL: $*" >&2
  exit 1
}

expect_failure()
{
  local expected=$1
  shift
  local output
  if output=$("$@" 2>&1); then
    fail "command unexpectedly succeeded: $*"
  fi
  if [[ "${output}" != *"${expected}"* ]]; then
    echo "${output}" >&2
    fail "failure did not contain: ${expected}"
  fi
}

make_os_release()
{
  local path=$1
  local id=$2
  local version=$3
  printf 'ID=%s\nVERSION_ID="%s"\n' "${id}" "${version}" > "${path}"
}

make_fixture()
{
  local fixture=$1
  mkdir -p "${fixture}/dependencies" "${fixture}/vendor/mtranserver"
  cp "${installer}" "${fixture}/dependencies/auto_install.sh"
  cp "${root}/dependencies/verify_runtime_data.py" "${fixture}/dependencies/verify_runtime_data.py"
  printf '{"version":"4.0.33"}\n' > "${fixture}/vendor/mtranserver/package.json"
  printf 'lockfileVersion = 1\n' > "${fixture}/vendor/mtranserver/bun.lock"
}

make_fake_path()
{
  local fake_bin=$1
  local actions=$2
  mkdir -p "${fake_bin}"

  cat > "${fake_bin}/dpkg-query" <<'EOF'
#!/usr/bin/env bash
case "${@: -1}" in
  pkg-config | npm) exit 1 ;;
esac
printf 'install ok installed\n'
EOF
  cat > "${fake_bin}/sudo" <<EOF
#!/usr/bin/env bash
printf 'sudo %s\n' "\$*" >> "${actions}"
exit 0
EOF
  cat > "${fake_bin}/file" <<'EOF'
#!/usr/bin/env bash
printf 'ELF 64-bit LSB executable, x86-64\n'
EOF
  for command in npm rsync; do
    cat > "${fake_bin}/${command}" <<EOF
#!/usr/bin/env bash
printf '${command} %s\n' "\$*" >> "${actions}"
exit 97
EOF
  done
  chmod +x "${fake_bin}"/*
}

make_valid_runtime()
{
  local fixture=$1
  local actions=$2
  local model_dir="${fixture}/models/en_zh-Hans"
  local records_dir="${fixture}/runtime/config"
  local runtime_bin="${fixture}/runtime/bin"
  local tools_bin="${fixture}/dependencies/tools/node_modules/.bin"
  mkdir -p "${model_dir}" "${records_dir}" "${runtime_bin}" "${tools_bin}"

  local model='model-data'
  local lex='lex-data'
  local src='source-vocab'
  local trg='target-vocab'
  printf '%s' "${model}" > "${model_dir}/model.enzh.intgemm.alphas.bin"
  printf '%s' "${lex}" > "${model_dir}/lex.50.50.enzh.s2t.bin"
  printf '%s' "${src}" > "${model_dir}/srcvocab.enzh.spm"
  printf '%s' "${trg}" > "${model_dir}/trgvocab.enzh.spm"

  local model_hash lex_hash src_hash trg_hash
  model_hash=$(sha256sum "${model_dir}/model.enzh.intgemm.alphas.bin" | cut -d' ' -f1)
  lex_hash=$(sha256sum "${model_dir}/lex.50.50.enzh.s2t.bin" | cut -d' ' -f1)
  src_hash=$(sha256sum "${model_dir}/srcvocab.enzh.spm" | cut -d' ' -f1)
  trg_hash=$(sha256sum "${model_dir}/trgvocab.enzh.spm" | cut -d' ' -f1)

  cat > "${records_dir}/records.json" <<EOF
{"data":[
 {"sourceLanguage":"en","targetLanguage":"zh-Hans","fileType":"model","version":"1.0","decompressedHash":"${model_hash}","decompressedSize":${#model},"attachment":{"filename":"model.enzh.intgemm.alphas.bin.zst"}},
 {"sourceLanguage":"en","targetLanguage":"zh-Hans","fileType":"lex","version":"1.0","decompressedHash":"${lex_hash}","decompressedSize":${#lex},"attachment":{"filename":"lex.50.50.enzh.s2t.bin.zst"}},
 {"sourceLanguage":"en","targetLanguage":"zh-Hans","fileType":"srcvocab","version":"1.0","decompressedHash":"${src_hash}","decompressedSize":${#src},"attachment":{"filename":"srcvocab.enzh.spm.zst"}},
 {"sourceLanguage":"en","targetLanguage":"zh-Hans","fileType":"trgvocab","version":"1.0","decompressedHash":"${trg_hash}","decompressedSize":${#trg},"attachment":{"filename":"trgvocab.enzh.spm.zst"}}
]}
EOF

  cat > "${runtime_bin}/mtranserver" <<EOF
#!/usr/bin/env bash
printf 'sidecar %s\n' "\$*" >> "${actions}"
exit 96
EOF
  cat > "${tools_bin}/bun" <<EOF
#!/usr/bin/env bash
if [[ "\${1:-}" == '--version' ]]; then
  printf '1.3.14\n'
  exit 0
fi
printf 'bun %s\n' "\$*" >> "${actions}"
exit 95
EOF
  chmod +x "${runtime_bin}/mtranserver" "${tools_bin}/bun"
}

bash -n "${installer}"

ubuntu_release="${tmp_root}/ubuntu-release"
other_release="${tmp_root}/other-release"
make_os_release "${ubuntu_release}" ubuntu 22.04
make_os_release "${other_release}" debian 12

expect_failure "Ubuntu 22.04" env \
  MTRAN_OS_RELEASE_FILE="${other_release}" \
  MTRAN_MACHINE=x86_64 \
  ROS_DISTRO=humble \
  bash "${installer}"

expect_failure "x86_64 or aarch64" env \
  MTRAN_OS_RELEASE_FILE="${ubuntu_release}" \
  MTRAN_MACHINE=ppc64le \
  ROS_DISTRO=humble \
  bash "${installer}"

expect_failure "ROS2 Humble" env -u ROS_DISTRO \
  MTRAN_OS_RELEASE_FILE="${ubuntu_release}" \
  MTRAN_MACHINE=x86_64 \
  bash "${installer}"

missing_vendor="${tmp_root}/missing-vendor"
mkdir -p "${missing_vendor}/dependencies"
cp "${installer}" "${missing_vendor}/dependencies/auto_install.sh"
expect_failure "vendor/mtranserver" env \
  MTRAN_OS_RELEASE_FILE="${ubuntu_release}" \
  MTRAN_MACHINE=x86_64 \
  ROS_DISTRO=humble \
  bash "${missing_vendor}/dependencies/auto_install.sh"

fixture="${tmp_root}/copied-workspace/src/mtran"
actions="${tmp_root}/actions.log"
fake_bin="${tmp_root}/fake-bin"
: > "${actions}"
make_fixture "${fixture}"
make_fake_path "${fake_bin}" "${actions}"
make_valid_runtime "${fixture}" "${actions}"

PATH="${fake_bin}:/usr/bin:/bin" \
MTRAN_OS_RELEASE_FILE="${ubuntu_release}" \
MTRAN_MACHINE=x86_64 \
ROS_DISTRO=humble \
bash "${fixture}/dependencies/auto_install.sh"

if grep -Eq '^(npm|rsync|bun|sidecar) ' "${actions}"; then
  cat "${actions}" >&2
  fail "valid generated artifacts were rebuilt or downloaded"
fi
if grep -Eq '^sudo ' "${actions}"; then
  cat "${actions}" >&2
  fail "already-installed apt dependencies still invoked sudo"
fi

build_fixture="${tmp_root}/build-workspace/src/mtran"
build_actions="${tmp_root}/build-actions.log"
build_fake_bin="${tmp_root}/build-fake-bin"
make_fixture "${build_fixture}"
make_fake_path "${build_fake_bin}" "${build_actions}"
make_valid_runtime "${build_fixture}" "${build_actions}"
rm "${build_fixture}/runtime/bin/mtranserver"

cat > "${build_fake_bin}/rsync" <<'EOF'
#!/usr/bin/env bash
source_dir=${@: -2:1}
destination=${@: -1}
mkdir -p "${destination}"
cp -a "${source_dir}/." "${destination}/"
EOF
cat > "${build_fixture}/dependencies/tools/node_modules/.bin/bun" <<EOF
#!/usr/bin/env bash
if [[ "\${1:-}" == '--version' ]]; then
  printf '1.3.14\n'
  exit 0
fi
if [[ "\${BUN_INSTALL_CACHE_DIR:-}" != "${build_fixture}/dependencies/tools/bun-cache" ]]; then
  echo 'BUN_INSTALL_CACHE_DIR was not propagated' >&2
  exit 94
fi
if [[ "\${ELECTRON_SKIP_BINARY_DOWNLOAD:-}" != '1' ]]; then
  echo 'ELECTRON_SKIP_BINARY_DOWNLOAD was not propagated' >&2
  exit 93
fi
if [[ "\$(command -v bun)" != "${build_fixture}/dependencies/tools/node_modules/.bin/bun" ]]; then
  echo 'workspace-local Bun was not added to PATH' >&2
  exit 92
fi
printf 'bun %s\n' "\$*" >> "${build_actions}"
if [[ "\${1:-}" == 'run' && "\${2:-}" == 'build' ]]; then
  mkdir -p dist
  printf '#!/usr/bin/env bash\nexit 0\n' > dist/mtranserver
  chmod +x dist/mtranserver
fi
EOF
chmod +x "${build_fake_bin}/rsync" \
  "${build_fixture}/dependencies/tools/node_modules/.bin/bun"

PATH="${build_fake_bin}:/usr/bin:/bin" \
MTRAN_OS_RELEASE_FILE="${ubuntu_release}" \
MTRAN_MACHINE=x86_64 \
ROS_DISTRO=humble \
bash "${build_fixture}/dependencies/auto_install.sh"

test -x "${build_fixture}/runtime/bin/mtranserver"
grep -Fq 'bun install --frozen-lockfile' "${build_actions}"
grep -Fq 'bun run build' "${build_actions}"

printf 'auto_install tests passed\n'
