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

# Requires:
#   rustup component add llvm-tools-preview
#   cargo install cargo-llvm-cov --locked

# Optional:
#   COVERAGE_FORCE_CLEAN=1  Force `cargo llvm-cov clean --workspace` before the run.
#                           Default behavior is to reuse existing llvm-cov build artifacts.
#   RPKI_SKIP_HEAVY_SCRIPT_REPLAY_TESTS=1  Skip replay/matrix integration tests that
#                           spawn shell pipelines and can trigger separate release builds.
#                           coverage.sh enables this by default.
#   RPKI_SKIP_HEAVY_BLACKBOX_TESTS=1  Skip slower blackbox CLI/script integration tests
#                           that provide low incremental coverage per wall-clock second.
#                           coverage.sh enables this by default.
#   RPKI_SKIP_HEAVY_CRYPTO_TESTS=1  Skip slower OpenSSL-heavy certificate generation tests
#                           that provide low incremental coverage per wall-clock second.
#                           coverage.sh enables this by default.

run_out="$(mktemp)"
text_out="$(mktemp)"
html_out="$(mktemp)"

cleanup() {
  rm -f "$run_out" "$text_out" "$html_out"
}
trap cleanup EXIT

IGNORE_REGEX='repository_view_stats\.rs|db_stats\.rs|rrdp_state_dump\.rs|ccr_dump\.rs|ccr_verify\.rs|ccr_to_routinator_csv\.rs|ccr_to_compare_views\.rs|cir_materialize\.rs|cir_extract_inputs\.rs|cir_drop_report\.rs|cir_ta_only_fixture\.rs|cir_dump_reject_list\.rs|rpki_object_parse\.rs|rpki_query_indexer\.rs|rpki_query_service\.rs|triage_ccr_cir_pair\.rs|rpki_artifact_metrics|rpki_inter_rp_metrics|rpki_daemon\.rs|sequence_triage_ccr_cir|ccr_state_compare\.rs|cir_state_compare\.rs|cir_probe_rpki_client_cache\.rs|ccr/compare_view\.rs|progress_log\.rs|cli\.rs|validation/run_tree_from_tal\.rs|validation/tree_parallel\.rs|validation/tree_runner|validation/from_tal\.rs|sync/store_projection\.rs|sync/repo\.rs|sync/rrdp|(^|/)storage(/|\.rs$)|cir/materialize\.rs'

# Preserve colored output even though we post-process output by running under a pseudo-TTY.
# We run tests only once, then generate both CLI text + HTML reports without rerunning tests.
set +e

if [ "${COVERAGE_FORCE_CLEAN:-0}" = "1" ]; then
  cargo llvm-cov clean --workspace >/dev/null 2>&1
  echo "coverage mode: clean build (COVERAGE_FORCE_CLEAN=1)"
else
  echo "coverage mode: reuse existing llvm-cov artifacts (default)"
fi

export RPKI_SKIP_HEAVY_SCRIPT_REPLAY_TESTS="${RPKI_SKIP_HEAVY_SCRIPT_REPLAY_TESTS:-1}"
export RPKI_SKIP_HEAVY_BLACKBOX_TESTS="${RPKI_SKIP_HEAVY_BLACKBOX_TESTS:-1}"
export RPKI_SKIP_HEAVY_CRYPTO_TESTS="${RPKI_SKIP_HEAVY_CRYPTO_TESTS:-1}"

# 1) Run tests once to collect coverage data (no report).
script -q -e -c "CARGO_TERM_COLOR=always cargo llvm-cov --no-report" "$run_out" >/dev/null 2>&1
run_status="$?"

# 2) CLI summary report + fail-under gate (no test rerun).
script -q -e -c "CARGO_TERM_COLOR=always cargo llvm-cov report --fail-under-lines 90 --ignore-filename-regex '$IGNORE_REGEX'" "$text_out" >/dev/null 2>&1
text_status="$?"

# 3) HTML report (no test rerun).
script -q -e -c "CARGO_TERM_COLOR=always cargo llvm-cov report --html --ignore-filename-regex '$IGNORE_REGEX'" "$html_out" >/dev/null 2>&1
html_status="$?"

set -e

strip_script_noise() {
  tr -d '\r' | sed '/^Script \(started\|done\) on /d'
}

strip_ansi_for_parse() {
  awk '
    {
      line = $0
      gsub(/\033\[[0-9;]*[A-Za-z]/, "", line) # CSI escapes
      gsub(/\033\([A-Za-z]/, "", line)        # charset escapes (e.g., ESC(B)
      gsub(/\r/, "", line)
      print line
    }
  '
}

cat "$run_out" | strip_script_noise
cat "$text_out" | strip_script_noise
cat "$html_out" | strip_script_noise

cat "$run_out" | strip_ansi_for_parse | awk '
  BEGIN {
    passed=0; failed=0; ignored=0; measured=0; filtered=0;
  }
  /^test result: / {
    if (match($0, /([0-9]+) passed; ([0-9]+) failed; ([0-9]+) ignored; ([0-9]+) measured; ([0-9]+) filtered out;/, m)) {
      passed += m[1]; failed += m[2]; ignored += m[3]; measured += m[4]; filtered += m[5];
    }
  }
  END {
    executed = passed + failed;
    total = passed + failed + ignored + measured;
    printf("\nTEST SUMMARY (all suites): passed=%d failed=%d ignored=%d measured=%d filtered_out=%d executed=%d total=%d\n",
           passed, failed, ignored, measured, filtered, executed, total);
  }
'

echo
echo "HTML report: target/llvm-cov/html/index.html"

status="$text_status"
if [ "$run_status" -ne 0 ]; then status="$run_status"; fi
if [ "$html_status" -ne 0 ]; then status="$html_status"; fi
exit "$status"
