#!/usr/bin/env bash
# run-test.sh — Main test harness entry point.
#
# Creates a headless VirtualBox VM from a Windows ISO, runs the cloud-setup
# skill's installation steps inside it, and reports pass/fail per step.
# On failure: captures logs, restores to the last good snapshot, and exits.
#
# Usage:
#   run-test.sh --iso <path-to-windows.iso>   # First run
#   run-test.sh                                 # Subsequent runs (uses existing VM)
#   run-test.sh --skip-wsl                      # Skip WSL/Redis/PostgreSQL steps
#   run-test.sh --step 3                        # Resume from step 03
#   run-test.sh --keep-vm                       # Don't destroy VM after test
#   run-test.sh --destroy                       # Just tear down the VM

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/config.sh"

# ─── Argument Parsing ───────────────────────────────────────

ISO_PATH=""
SKIP_WSL=false
START_STEP=0
KEEP_VM=false
DESTROY_ONLY=false

while [[ $# -gt 0 ]]; do
  case "$1" in
    --iso)       ISO_PATH="$2"; shift 2 ;;
    --skip-wsl)  SKIP_WSL=true; shift ;;
    --step)      START_STEP="$2"; shift 2 ;;
    --keep-vm)   KEEP_VM=true; shift ;;
    --destroy)   DESTROY_ONLY=true; shift ;;
    -h|--help)
      echo "Usage: run-test.sh [--iso <path>] [--skip-wsl] [--step N] [--keep-vm] [--destroy]"
      echo ""
      echo "  --iso <path>     Path to Windows 11 ISO (required on first run)"
      echo "  --skip-wsl       Skip WSL/Redis/PostgreSQL steps (Windows tools only)"
      echo "  --step <N>       Start from step N (0-9, requires existing VM)"
      echo "  --keep-vm        Don't destroy VM after test (for debugging)"
      echo "  --destroy        Just destroy the VM and exit"
      echo ""
      echo "Prerequisites:"
      echo "  - VirtualBox 7+ installed"
      echo "  - Windows 11 ISO (evaluation: https://www.microsoft.com/evalcenter)"
      echo "  - ~25 GB free disk space"
      exit 0
      ;;
    *) log_fail "Unknown flag: $1. Use --help for usage."; exit 1 ;;
  esac
done

# Export for step scripts
export SKIP_WSL

require_vbox
ensure_dirs

# ─── Destroy Mode ──────────────────────────────────────────

if $DESTROY_ONLY; then
  bash "$SCRIPT_DIR/vm-manager.sh" destroy
  exit 0
fi

# ─── VM Exec Helpers (used by step scripts) ─────────────────
# These wrap vm-exec.sh so step scripts can call vm_exec directly.

vm_exec() {
  bash "$SCRIPT_DIR/vm-exec.sh" "$@"
}
export -f vm_exec
export SCRIPT_DIR

# ─── Step Runner ───────────────────────────────────────────

TOTAL_PASS=0
TOTAL_FAIL=0
TOTAL_SKIP=0
STEP_TIMES=()
STEP_RESULTS=()

run_step() {
  local step_file="$1"
  local step_num
  step_num=$(basename "$step_file" | cut -d'-' -f1)
  local step_name=""

  # Skip steps before START_STEP
  if (( 10#$step_num < 10#$START_STEP )); then
    return 0
  fi

  # Skip WSL steps if --skip-wsl
  if $SKIP_WSL; then
    case "$step_num" in
      01|06|07)
        # Source to get step_name
        source "$step_file"
        STEP_RESULTS+=("SKIP|$step_name|0")
        TOTAL_SKIP=$((TOTAL_SKIP + 1))
        log_warn "Skipping: $step_name (--skip-wsl)"
        return 0
        ;;
    esac
  fi

  # Source the step to get step_name, run(), verify()
  source "$step_file"
  log_step "Step $step_num: $step_name"

  local start_time
  start_time=$(date +%s)

  # Create a log file for this step
  local log_file="$LOG_DIR/step-${step_num}-$(timestamp).log"
  log_info "Log: $log_file"

  # Run the step
  local run_ok=true
  if ! run >> "$log_file" 2>&1; then
    run_ok=false
  fi

  # Verify
  local verify_ok=true
  if $run_ok; then
    if ! verify >> "$log_file" 2>&1; then
      verify_ok=false
    fi
  fi

  local end_time
  end_time=$(date +%s)
  local duration=$((end_time - start_time))

  if $run_ok && $verify_ok; then
    log_pass "$step_name (${duration}s)"
    STEP_RESULTS+=("PASS|$step_name|$duration")
    TOTAL_PASS=$((TOTAL_PASS + 1))
  else
    log_fail "$step_name (${duration}s)"
    STEP_RESULTS+=("FAIL|$step_name|$duration")
    TOTAL_FAIL=$((TOTAL_FAIL + 1))

    # Print last 20 lines of log
    echo ""
    log_info "Last 20 lines of $log_file:"
    tail -20 "$log_file" 2>/dev/null || true
    echo ""

    # Failure handling: restore snapshot and exit
    handle_failure "$step_num"
    return 1
  fi
}

handle_failure() {
  local step_num="$1"
  log_info "Handling failure at step $step_num..."

  # Determine which snapshot to restore
  local restore_to="$SNAPSHOT_CLEAN"
  if (( 10#$step_num > 1 )) && vm_has_snapshot "$SNAPSHOT_WSL"; then
    restore_to="$SNAPSHOT_WSL"
  fi

  if ! $KEEP_VM; then
    log_info "Restoring VM to snapshot '$restore_to'..."
    bash "$SCRIPT_DIR/vm-manager.sh" restore "$restore_to" 2>/dev/null || true
    log_info "VM restored. Re-run to retry from scratch."
  else
    log_info "VM kept running (--keep-vm). Debug via:"
    log_info "  VBoxManage startvm $VM_NAME --type gui"
    log_info "  Or: bash vm-exec.sh cmd \"<your command>\""
  fi
}

# ─── Main Flow ─────────────────────────────────────────────

echo ""
echo -e "${BOLD}=========================================="
echo " bigstack-cloud-setup Test Harness"
echo -e "==========================================${RESET}"
echo ""

START_TIME=$(date +%s)

# --- Phase 1: Ensure VM exists ---

if ! vm_exists; then
  if [[ -z "$ISO_PATH" ]]; then
    log_fail "No VM found and no --iso provided."
    echo ""
    echo "  First run: run-test.sh --iso <path-to-windows-11.iso>"
    echo "  Get an evaluation ISO: https://www.microsoft.com/evalcenter"
    exit 1
  fi
  bash "$SCRIPT_DIR/vm-manager.sh" create --iso "$ISO_PATH"
elif ! vm_running; then
  # VM exists but not running — figure out which snapshot to restore
  if (( START_STEP > 1 )) && vm_has_snapshot "$SNAPSHOT_WSL"; then
    log_info "Restoring to WSL snapshot..."
    bash "$SCRIPT_DIR/vm-manager.sh" restore "$SNAPSHOT_WSL"
  elif vm_has_snapshot "$SNAPSHOT_CLEAN"; then
    log_info "Restoring to clean Windows snapshot..."
    bash "$SCRIPT_DIR/vm-manager.sh" restore "$SNAPSHOT_CLEAN"
  else
    log_info "Starting existing VM..."
    "$VBOXMANAGE" startvm "$VM_NAME" --type headless
    wait_for_guest
  fi
else
  log_info "VM already running"
fi

# --- Phase 2: Run steps ---

STEPS_DIR="$SCRIPT_DIR/steps"
FAILED=false

for step_file in "$STEPS_DIR"/[0-9]*.sh; do
  [[ -f "$step_file" ]] || continue
  if ! run_step "$step_file"; then
    FAILED=true
    break
  fi
done

# --- Phase 3: Summary ---

END_TIME=$(date +%s)
TOTAL_TIME=$((END_TIME - START_TIME))
TOTAL_MIN=$((TOTAL_TIME / 60))
TOTAL_SEC=$((TOTAL_TIME % 60))

echo ""
echo -e "${BOLD}=========================================="
echo " Test Results"
echo -e "==========================================${RESET}"
echo ""

for result in "${STEP_RESULTS[@]}"; do
  IFS='|' read -r status name duration <<< "$result"
  case "$status" in
    PASS) printf "  ${GREEN}[PASS]${RESET} %-45s (%ss)\n" "$name" "$duration" ;;
    FAIL) printf "  ${RED}[FAIL]${RESET} %-45s (%ss)\n" "$name" "$duration" ;;
    SKIP) printf "  ${YELLOW}[SKIP]${RESET} %-45s\n" "$name" ;;
  esac
done

echo ""
echo -e "${BOLD}==========================================${RESET}"
echo "  $TOTAL_PASS passed, $TOTAL_FAIL failed, $TOTAL_SKIP skipped"
echo "  Total time: ${TOTAL_MIN}m ${TOTAL_SEC}s"
echo "  Logs: $LOG_DIR"
echo -e "${BOLD}==========================================${RESET}"
echo ""

# --- Phase 4: Cleanup ---

if ! $KEEP_VM && ! $FAILED; then
  log_info "Destroying test VM..."
  bash "$SCRIPT_DIR/vm-manager.sh" destroy --keep-logs
elif $FAILED; then
  log_info "VM preserved for debugging (failure occurred)"
  log_info "  Re-run:  run-test.sh --step $START_STEP"
  log_info "  Destroy: run-test.sh --destroy"
fi

if $FAILED; then
  exit 1
fi
