#!/bin/bash
# run_trim_test.sh
#
# PURPOSE:
#   Run trim_excess_metadata.sh against the prepared lab environment on
#   p4c-nyc-03 in three passes:
#     1. Dry run  — preview only, no changes
#     2. Live run — execute all phases (no snap yet)
#     3. Snap run — same as live but also executes Phase 17 (p4 snap)
#
#   After the snap run, this script prints the journal patch path and the
#   exact commands needed to apply it and clean up orphaned archives.
#
# RUNS ON: p4c-bos-01 (as the perforce OS user)
#
# PREREQ: setup_lab.sh has already been run successfully.
#
# USAGE:
#   cd /home/perforce/tem
#   bash test/run_trim_test.sh
#
#   Or with explicit tag:
#   bash test/run_trim_test.sh [site_tag]   (default: gf)

set -uo pipefail

# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------

SITE_TAG="${1:-gf}"
NYC03="p4c-nyc-03"
SDP_INSTANCE=1
TEM_DIR="/home/perforce/tem"
TRIM_SCRIPT="${TEM_DIR}/trim_excess_metadata.sh"
P4CONFIG_GF="${TEM_DIR}/.p4config.gf"

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

H1="============================================================"
H2="------------------------------------------------------------"

msg()  { echo -e "$*"; }
hdr()  { msg "\n${H1}\n$*\n${H2}"; }
step() { msg "  --> $*"; }
ok()   { msg "  ✅  $*"; }
warn() { msg "  ⚠️   $*"; }
fail() { msg "  ❌  $*"; }

check_exit() {
   local code="$1" label="$2" expected="${3:-0}"
   if [[ "$code" -eq "$expected" ]]; then
      ok "${label}: exit ${code} (expected)"
   else
      warn "${label}: exit ${code} (expected ${expected})"
   fi
}

# ---------------------------------------------------------------------------
# Pre-flight
# ---------------------------------------------------------------------------

hdr "Pre-flight"

[[ -f "$TRIM_SCRIPT" ]] || { fail "Trim script not found: ${TRIM_SCRIPT}"; exit 1; }
[[ -f "$P4CONFIG_GF" ]] || { fail "P4CONFIG not found: ${P4CONFIG_GF} — run setup_lab.sh first"; exit 1; }
[[ -f "${TEM_DIR}/keep_users.gf.txt" ]] || { fail "keep_users.gf.txt not found — run setup_lab.sh first"; exit 1; }
[[ -f "${TEM_DIR}/keep_groups.gf.txt" ]] || { fail "keep_groups.gf.txt not found — run setup_lab.sh first"; exit 1; }

export P4CONFIG="$P4CONFIG_GF"
cd "$TEM_DIR"

step "Logging in to nyc-03 (using raw p4 login so ticket goes to .p4tickets) ..."
P4ADMIN_PASSWD="/p4/common/config/.p4passwd.p4_1.admin"
if [[ -f "$P4ADMIN_PASSWD" ]]; then
   p4 login -a < "$P4ADMIN_PASSWD" 2>&1 | grep -E "logged in|Success|Error" || true
else
   step "Warning: ${P4ADMIN_PASSWD} not found — you may need to log in manually."
fi

step "Verifying nyc-03 is a standalone commit server ..."
SERVER_INFO=$(p4 -ztag info -s 2>/dev/null)
SERVER_ID=$(echo "$SERVER_INFO"  | awk '/^[.][.][.] ServerID /     {print $3}')
SERVICES=$(echo "$SERVER_INFO"   | awk '/^[.][.][.] serverServices /{print $3}')
P4ROOT=$(echo "$SERVER_INFO"     | awk '/^[.][.][.] serverRoot /    {print $3}')

if [[ "$SERVICES" != "standard" ]]; then
   fail "nyc-03 services='${SERVICES}' — expected 'standard'. Run setup_lab.sh first."
   exit 1
fi
ok "nyc-03: ServerID=${SERVER_ID}, Services=${SERVICES}, P4ROOT=${P4ROOT}"

# Show current state before trim
msg ""
step "Current depots on nyc-03:"
p4 depots 2>/dev/null | awk '{print "    " $0}' || true
step "Current users on nyc-03:"
p4 users 2>/dev/null | awk '{print "    " $0}' || true

# ---------------------------------------------------------------------------
# Pass 1: Dry run
# ---------------------------------------------------------------------------

hdr "Pass 1: Dry Run (no changes)"

DRY_LOG="${TEM_DIR}/test_dry_run.log"
msg "Log: ${DRY_LOG}"
bash "$TRIM_SCRIPT" "$SITE_TAG" 2>&1 | tee "$DRY_LOG"
DRY_EXIT="${PIPESTATUS[0]}"
check_exit "$DRY_EXIT" "Dry run" 0

# ---------------------------------------------------------------------------
# Pass 2: Live Run (no snap)
# ---------------------------------------------------------------------------

hdr "Pass 2: Live Run (-y, no snap)"

LIVE_LOG="${TEM_DIR}/test_live_run.log"
msg "Log: ${LIVE_LOG}"
bash "$TRIM_SCRIPT" "$SITE_TAG" -y 2>&1 | tee "$LIVE_LOG"
LIVE_EXIT="${PIPESTATUS[0]}"
# Exit 4 = shelved CL failures (expected: shelved CLs in filtered depots have
# no archive content to delete).  0 also acceptable if shelved CLs already gone.
if [[ "$LIVE_EXIT" -eq 0 || "$LIVE_EXIT" -eq 4 ]]; then
   ok "Live run: exit ${LIVE_EXIT} (expected 0 or 4)"
else
   warn "Live run: exit ${LIVE_EXIT} (expected 0 or 4)"
fi

# ---------------------------------------------------------------------------
# Pass 3: Snap Run (-y -snap)
# ---------------------------------------------------------------------------

hdr "Pass 3: Snap Run (-y -snap)"

SNAP_LOG="${TEM_DIR}/test_snap_run.log"
msg "Log: ${SNAP_LOG}"
bash "$TRIM_SCRIPT" "$SITE_TAG" -y -snap 2>&1 | tee "$SNAP_LOG"
SNAP_EXIT="${PIPESTATUS[0]}"
if [[ "$SNAP_EXIT" -eq 0 || "$SNAP_EXIT" -eq 4 ]]; then
   ok "Snap run: exit ${SNAP_EXIT} (expected 0 or 4)"
else
   warn "Snap run: exit ${SNAP_EXIT} (expected 0 or 4)"
fi

# ---------------------------------------------------------------------------
# Journal patch and cleanup instructions
# ---------------------------------------------------------------------------

hdr "Journal Patch: Apply Instructions"

# Find the most recent journal patch file generated by the trim script
JNL=$(ls -t "${TEM_DIR}"/trim_excess_metadata.*.jnl 2>/dev/null | head -1 || true)

if [[ -z "$JNL" ]]; then
   msg "No journal patch file found. (All empty depots may have been deleted"
   msg "via the front-door method — no patch needed.)"
else
   ok "Journal patch file: ${JNL}"
   msg ""
   msg "The journal patch removes depot specs from db.domain for depots that"
   msg "p4d refused to delete via the front-door method (e.g. because db.storage"
   msg "entries remain from lazy copies into kept depot archives)."
   msg ""
   msg "To apply:"
   msg ""
   msg "  1. Copy patch to the p4d server (it must be on its local filesystem):"
   msg "     scp '${JNL}' perforce@${NYC03}:/tmp/"
   msg ""
   msg "  2. Stop p4d, apply, restart:"
   msg "     ssh perforce@${NYC03} \\"
   msg "       'sudo systemctl stop p4d_${SDP_INSTANCE} && \\"
   msg "        p4d -r ${P4ROOT} -jr /tmp/$(basename "$JNL") && \\"
   msg "        sudo systemctl start p4d_${SDP_INSTANCE}'"
   msg ""
   msg "  3. Verify data integrity:"
   msg "     export P4CONFIG=${P4CONFIG_GF}"
   msg "     p4 verify //jam/... //pb/..."
   msg ""
   msg "  4. Delete orphaned archive directories (from Phase 18 output above)."
   msg "     Example (adjust to match Phase 18 output):"
   msg "     ssh perforce@${NYC03} 'rm -rf /p4/${SDP_INSTANCE}/depots/depot'"
fi

# ---------------------------------------------------------------------------
# Final verification
# ---------------------------------------------------------------------------

hdr "Final State Verification"

step "Waiting a moment for any service restart to settle ..."
sleep 3

step "Depots on nyc-03 after trim:"
p4 depots 2>/dev/null | awk '{print "    " $0}' || true

step "Users on nyc-03 after trim:"
p4 users 2>/dev/null | awk '{print "    " $0}' || true

step "Groups on nyc-03 after trim:"
p4 groups 2>/dev/null | awk '{print "    " $0}' || true

step "Server specs on nyc-03 after trim:"
p4 servers 2>/dev/null | awk '{print "    " $0}' || true

msg ""
msg "${H1}"
msg "Trim test run complete."
msg ""
msg "Expected outcomes (after journal patch applied):"
msg "  Depots : jam, pb, Perforce (remote), spec, unload"
msg "  Users  : perforce only"
msg "  Groups : testers only"
msg "  Servers: p4d_commit_gf only"
msg "  p4 verify //jam/... //pb/... — clean"
msg "${H1}"
