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

workspace_root="$(git rev-parse --show-toplevel)"
cd "${workspace_root}"

mode="fresh"
case "${1:-}" in
  "" | --fresh)
    mode="fresh"
    ;;
  --warm)
    mode="warm"
    ;;
  -h | --help)
    cat <<'EOF'
usage: buildbuddy-ci-workspace [--fresh|--warm]

Modes:
  --fresh  Run on temporary output roots and remove them afterwards.
  --warm   Reuse a stable output root for repeated local/agent gates.
EOF
    exit 0
    ;;
  *)
    echo "unknown argument: $1" >&2
    exit 2
    ;;
esac

created_temp=0
if [[ "${mode}" == "warm" ]]; then
  output_root="${MEERKAT_BUILDBUDDY_OUTPUT_ROOT:-${XDG_CACHE_HOME:-${HOME}/.cache}/meerkat/buildbuddy-ci-workspace}"
else
  output_root="${MEERKAT_BUILDBUDDY_OUTPUT_ROOT:-$(mktemp -d "${TMPDIR:-/tmp}/meerkat-bb-ci-workspace.XXXXXX")}"
  if [[ -z "${MEERKAT_BUILDBUDDY_OUTPUT_ROOT:-}" ]]; then
    created_temp=1
  fi
fi

run_id="$(date +%Y%m%d-%H%M%S)"
log_root="${MEERKAT_BUILDBUDDY_LOG_ROOT:-${XDG_CACHE_HOME:-${HOME}/.cache}/meerkat/buildbuddy-ci-workspace-logs/${run_id}-${mode}}"
summary_path="${log_root}/summary.tsv"
context_path="${log_root}/benchmark-context.txt"

cleanup() {
  if [[ "${created_temp}" == "1" && -d "${output_root}" ]]; then
    chmod -R u+w "${output_root}" 2>/dev/null || true
    rm -rf "${output_root}"
  fi
}
trap cleanup EXIT

write_context() {
  scripts/buildbuddy-write-context --mode "${mode}" --output-root "${output_root}" >"${context_path}"
  printf 'name\tstatus\twall_seconds\tlog\tcommand\n' >"${summary_path}"
}

summarize_log() {
  local name="$1"
  local status="$2"
  local log="$3"
  if [[ "${status}" == "0" ]]; then
    printf 'PASS %s\n' "${name}"
  else
    printf 'FAIL(%s) %s\n' "${status}" "${name}"
  fi
  grep -E 'INFO: Elapsed time:|INFO: Build completed|Executed |ERROR:|FAILED' "${log}" | tail -8 || true
}

run_lane() {
  local lane="$1"
  local command="$2"
  local log="$3"
  shift 3
  (
    export MEERKAT_BUILDBUDDY_OUTPUT_ROOT="${output_root}"
    if [[ "${mode}" == "warm" ]]; then
      export BUILDBUDDY_MAX_IDLE_SECS="${BUILDBUDDY_MAX_IDLE_SECS:-600}"
    else
      export BUILDBUDDY_MAX_IDLE_SECS="${BUILDBUDDY_MAX_IDLE_SECS:-5}"
    fi
    export RUST_LANE_ID="${lane}"
    export BUILDBUDDY_BAZEL_COMMAND="${command}"
    ./scripts/buildbuddy-bazel-poc "$@"
  ) >"${log}" 2>&1
}

test_command="workspace-fast-clippy-rbe"
clippy_command="workspace-build-clippy-rbe"
system_e2e_command="e2e-system-rbe"
test_log="${log_root}/${test_command}.log"
clippy_log="${log_root}/${clippy_command}.log"
system_e2e_log="${log_root}/${system_e2e_command}.log"
test_status_file="${log_root}/${test_command}.status"
clippy_status_file="${log_root}/${clippy_command}.status"
system_e2e_status_file="${log_root}/${system_e2e_command}.status"
test_wall_file="${log_root}/${test_command}.wall"
clippy_wall_file="${log_root}/${clippy_command}.wall"
system_e2e_wall_file="${log_root}/${system_e2e_command}.wall"
mkdir -p "${output_root}" "${log_root}"
write_context

start_seconds="$(date +%s)"

(
  set +e
  lane_start_seconds="$(date +%s)"
  run_lane ci-workspace-fast-clippy-rbe "${test_command}" "${test_log}" --jobs=64
  lane_status="$?"
  lane_end_seconds="$(date +%s)"
  echo "${lane_status}" >"${test_status_file}"
  echo "$((lane_end_seconds - lane_start_seconds))" >"${test_wall_file}"
) &
test_pid="$!"
(
  set +e
  lane_start_seconds="$(date +%s)"
  run_lane ci-workspace-build-clippy-rbe "${clippy_command}" "${clippy_log}" --jobs=64 --color=no --curses=no
  lane_status="$?"
  lane_end_seconds="$(date +%s)"
  echo "${lane_status}" >"${clippy_status_file}"
  echo "$((lane_end_seconds - lane_start_seconds))" >"${clippy_wall_file}"
) &
clippy_pid="$!"
(
  set +e
  lane_start_seconds="$(date +%s)"
  run_lane ci-e2e-system-rbe "${system_e2e_command}" "${system_e2e_log}" --jobs=64
  lane_status="$?"
  lane_end_seconds="$(date +%s)"
  echo "${lane_status}" >"${system_e2e_status_file}"
  echo "$((lane_end_seconds - lane_start_seconds))" >"${system_e2e_wall_file}"
) &
system_e2e_pid="$!"

wait "${test_pid}" || true
wait "${clippy_pid}" || true
wait "${system_e2e_pid}" || true

end_seconds="$(date +%s)"
test_status="$(cat "${test_status_file}" 2>/dev/null || echo 1)"
clippy_status="$(cat "${clippy_status_file}" 2>/dev/null || echo 1)"
system_e2e_status="$(cat "${system_e2e_status_file}" 2>/dev/null || echo 1)"
wall_seconds="$((end_seconds - start_seconds))"
test_wall="$(cat "${test_wall_file}" 2>/dev/null || echo "${wall_seconds}")"
clippy_wall="$(cat "${clippy_wall_file}" 2>/dev/null || echo "${wall_seconds}")"
system_e2e_wall="$(cat "${system_e2e_wall_file}" 2>/dev/null || echo "${wall_seconds}")"
printf '%s\t%s\t%s\t%s\t%s\n' "${test_command}" "${test_status}" "${test_wall}" "${test_log}" "BUILDBUDDY_BAZEL_COMMAND=${test_command} ./scripts/buildbuddy-bazel-poc --jobs=64" >>"${summary_path}"
printf '%s\t%s\t%s\t%s\t%s\n' "${clippy_command}" "${clippy_status}" "${clippy_wall}" "${clippy_log}" "BUILDBUDDY_BAZEL_COMMAND=${clippy_command} ./scripts/buildbuddy-bazel-poc --jobs=64 --color=no --curses=no" >>"${summary_path}"
printf '%s\t%s\t%s\t%s\t%s\n' "${system_e2e_command}" "${system_e2e_status}" "${system_e2e_wall}" "${system_e2e_log}" "BUILDBUDDY_BAZEL_COMMAND=${system_e2e_command} ./scripts/buildbuddy-bazel-poc --jobs=64" >>"${summary_path}"

printf 'BuildBuddy workspace CI (%s) wall: %ss\n' "${mode}" "${wall_seconds}"
summarize_log "${test_command}" "${test_status}" "${test_log}"
summarize_log "${clippy_command}" "${clippy_status}" "${clippy_log}"
summarize_log "${system_e2e_command}" "${system_e2e_status}" "${system_e2e_log}"
printf 'logs: %s\n' "${log_root}"
printf 'summary: %s\n' "${summary_path}"
printf 'context: %s\n' "${context_path}"

if [[ "${test_status}" != "0" || "${clippy_status}" != "0" || "${system_e2e_status}" != "0" ]]; then
  exit 1
fi
