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

die() {
  echo "error: $*" >&2
  exit 2
}

usage() {
  cat <<'USAGE'
Usage:
  scripts/rerun/build-tipoc-binary.sh --output PATH [--source PATH]

Builds TiPOC from a temporary full clone of the clean source HEAD. The output
is activated only after Go build metadata reports vcs=git, the exact committed
revision, and vcs.modified=false. Linked Git worktrees are supported.
USAGE
}

source_path="$(pwd)"
output=""
while [[ $# -gt 0 ]]; do
  case "$1" in
    --source)
      [[ $# -ge 2 ]] || die "--source requires a value"
      source_path="$2"
      shift 2
      ;;
    --output)
      [[ $# -ge 2 ]] || die "--output requires a value"
      output="$2"
      shift 2
      ;;
    --help|-h)
      usage
      exit 0
      ;;
    *)
      die "unknown option: $1"
      ;;
  esac
done

[[ -n "$output" ]] || die "--output is required"
command -v git >/dev/null 2>&1 || die "git is required"
command -v go >/dev/null 2>&1 || die "go is required"

source_root="$(git -C "$source_path" rev-parse --show-toplevel 2>/dev/null)" ||
  die "source is not a Git worktree: $source_path"
revision="$(git -C "$source_root" rev-parse HEAD)"
[[ "$revision" =~ ^[0-9a-f]{40}$ ]] || die "source HEAD is not a full Git SHA"
[[ -z "$(git -C "$source_root" status --porcelain=v1)" ]] ||
  die "source worktree must be clean: $source_root"

build_root="$(mktemp -d "${TMPDIR:-/tmp}/tipoc-build.XXXXXX")"
staged_output=""
cleanup() {
  [[ -z "$staged_output" ]] || rm -f -- "$staged_output"
  rm -rf -- "$build_root"
}
trap cleanup EXIT

git clone --quiet --no-hardlinks "$source_root" "$build_root/repo"
git -C "$build_root/repo" checkout --quiet --detach "$revision"
[[ -z "$(git -C "$build_root/repo" status --porcelain=v1)" ]] ||
  die "temporary build clone is dirty"

candidate="$build_root/tipoc"
(
  cd "$build_root/repo"
  go build -buildvcs=true -trimpath -o "$candidate" ./cmd/tipoc/
)

build_info="$(go version -m "$candidate")" || die "cannot inspect built binary"
embedded_vcs="$(printf '%s\n' "$build_info" | sed -En 's/^[[:space:]]*build[[:space:]]+vcs=//p')"
embedded_revision="$(printf '%s\n' "$build_info" | sed -En 's/^[[:space:]]*build[[:space:]]+vcs\.revision=//p')"
embedded_modified="$(printf '%s\n' "$build_info" | sed -En 's/^[[:space:]]*build[[:space:]]+vcs\.modified=//p')"
[[ "$embedded_vcs" == "git" ]] || die "binary vcs is not git"
[[ "$embedded_revision" == "$revision" ]] ||
  die "binary vcs.revision does not match source HEAD"
[[ "$embedded_modified" == "false" ]] || die "binary vcs.modified is not false"

output_dir="$(dirname "$output")"
output_name="$(basename "$output")"
mkdir -p "$output_dir"
staged_output="$(mktemp "$output_dir/.${output_name}.tmp.XXXXXX")"
cp "$candidate" "$staged_output"
chmod 0755 "$staged_output"
mv -f "$staged_output" "$output"
staged_output=""

echo "source_revision=$revision"
echo "binary=$output"
echo "vcs=$embedded_vcs"
echo "vcs_revision=$embedded_revision"
echo "vcs_modified=$embedded_modified"
if command -v sha256sum >/dev/null 2>&1; then
  echo "sha256=$(sha256sum "$output" | awk '{print $1}')"
else
  echo "sha256=$(shasum -a 256 "$output" | awk '{print $1}')"
fi
