#!/usr/bin/env bash
# Project integrity check after a refactor.
# Runs fmt, clippy, build and tests for every Cargo world plus the Wear OS Gradle build.
# All stages run even if earlier ones fail. A summary table is printed at the end.
# Exit code equals the number of FAIL stages (WARN stages do not count).

set -u
set -o pipefail

REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
export JAVA_HOME="/opt/android-studio/jbr"

# Colors only when stdout is a terminal
if [[ -t 1 ]]; then
  C_RESET=$'\e[0m'
  C_RED=$'\e[31m'
  C_GREEN=$'\e[32m'
  C_YELLOW=$'\e[33m'
  C_BOLD=$'\e[1m'
else
  C_RESET=""
  C_RED=""
  C_GREEN=""
  C_YELLOW=""
  C_BOLD=""
fi

# Stage results, parallel arrays
STAGE_NAMES=()
STAGE_STATUS=()
STAGE_SECONDS=()
FAIL_COUNT=0

# run_stage <label> <working-dir> <severity> <cmd...>
#   severity = "fail" -> non-zero exit marks FAIL and increments FAIL_COUNT
#   severity = "warn" -> non-zero exit marks WARN, does not affect exit code
run_stage() {
  local label="$1"; shift
  local workdir="$1"; shift
  local severity="$1"; shift

  echo
  echo "${C_BOLD}=== ${label} ===${C_RESET}"
  echo "  dir: ${workdir}"
  echo "  cmd: $*"

  local start=$SECONDS
  local rc=0
  ( cd "$workdir" && "$@" ) || rc=$?
  local dur=$(( SECONDS - start ))

  STAGE_NAMES+=("$label")
  STAGE_SECONDS+=("$dur")

  if [[ $rc -eq 0 ]]; then
    STAGE_STATUS+=("PASS")
    echo "${C_GREEN}-> PASS${C_RESET} (${dur}s)"
  elif [[ "$severity" == "warn" ]]; then
    STAGE_STATUS+=("WARN")
    echo "${C_YELLOW}-> WARN (rc=${rc})${C_RESET} (${dur}s) -- not counted as failure"
  else
    STAGE_STATUS+=("FAIL")
    FAIL_COUNT=$(( FAIL_COUNT + 1 ))
    echo "${C_RED}-> FAIL (rc=${rc})${C_RESET} (${dur}s)"
  fi
}

# fmt is executed (not --check), so the working tree may be modified.
# clippy escalates warnings to errors per project convention.
# test uses -j 4 to avoid linker thrashing on a many-crate workspace.
cargo_world() {
  local world_label="$1"
  local dir="$2"
  run_stage "${world_label} :: fmt"    "$dir" fail cargo fmt
  run_stage "${world_label} :: clippy" "$dir" fail cargo clippy --all-targets --all-features -- -D warnings
  run_stage "${world_label} :: build"  "$dir" fail cargo build --all-targets
  run_stage "${world_label} :: test"   "$dir" fail cargo test -j 4
}

cargo_world "common"          "${REPO_ROOT}/common"
cargo_world "server"          "${REPO_ROOT}/server"
cargo_world "clients/desktop" "${REPO_ROOT}/clients/desktop"
cargo_world "experiments"     "${REPO_ROOT}/experiments"

# Wear OS (Gradle). lintDebug is WARN-only because legacy Android Lint findings
# would otherwise turn the script red regardless of the refactor under review.
# Instrumented tests are intentionally excluded (AVD MockWebServer hang, see memory).
WEAROS_DIR="${REPO_ROOT}/clients/wearos"
run_stage "wearos :: assembleDebug"     "$WEAROS_DIR" fail ./gradlew assembleDebug
run_stage "wearos :: lintDebug"         "$WEAROS_DIR" warn ./gradlew lintDebug
run_stage "wearos :: testDebugUnitTest" "$WEAROS_DIR" fail ./gradlew testDebugUnitTest

# Summary
echo
echo "${C_BOLD}========== SUMMARY ==========${C_RESET}"
total=0
for i in "${!STAGE_NAMES[@]}"; do
  name="${STAGE_NAMES[$i]}"
  status="${STAGE_STATUS[$i]}"
  dur="${STAGE_SECONDS[$i]}"
  total=$(( total + dur ))
  case "$status" in
    PASS) color="$C_GREEN" ;;
    WARN) color="$C_YELLOW" ;;
    FAIL) color="$C_RED" ;;
    *)    color="" ;;
  esac
  printf "  %s%-4s%s %5ds  %s\n" "$color" "$status" "$C_RESET" "$dur" "$name"
done
echo "  ----"
printf "  total: %ds across %d stages, %d failure(s)\n" "$total" "${#STAGE_NAMES[@]}" "$FAIL_COUNT"

exit "$FAIL_COUNT"
