#!/bin/bash
# ====================================================
# PR-D Production Check — OpenClaw Agent OS v2
# ====================================================
# One-shot safety gate: env → baseline → guard →
# deprecation → smoke → report.
# Every architecture PR must pass this gate first.
# ====================================================

set -e

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
cd "$ROOT_DIR"

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

START_TIME=$(date +%s)

# ─── Result state ───────────────────────────────────
ENV_PASS=false
BASELINE_PASS=false
GUARD_PASS=false
DEPRECATION_STATUS="PASS"
SMOKE_PASS=false
OVERALL_PASS=true

FAILED_STEP=""
FAIL_REASON=""
FAIL_FIX=""

BASELINE_COUNT=0
BASELINE_DURATION=0
BASELINE_LOG=""
DEPRECATION_COUNT=0

# ─── Helpers ────────────────────────────────────────

fail_step() {
  local step="$1" reason="$2" fix="$3"
  FAILED_STEP="$step"
  FAIL_REASON="$reason"
  FAIL_FIX="$fix"
  OVERALL_PASS=false
}

section() {
  echo ""
  echo -e "${CYAN}══════════════════════════════════════════════${NC}"
  echo -e "${CYAN}  $1${NC}"
  echo -e "${CYAN}══════════════════════════════════════════════${NC}"
  echo ""
}

# ─────────────────────────────────────────────────────
# Step 1: Environment Check
# ─────────────────────────────────────────────────────
section "Step 1: Environment Check"

check_ok() { echo -e "  ${GREEN}✓${NC} $1"; }
check_fail() { echo -e "  ${RED}✗${NC} $1"; fail_step "Environment" "$1" "$2"; }

# Node.js version
NODE_VERSION=$(node --version 2>/dev/null || echo "")
if [ -z "$NODE_VERSION" ]; then
  check_fail "Node.js not found" "Install Node.js >= 18"
else
  NODE_MAJOR=$(echo "$NODE_VERSION" | sed 's/v//' | cut -d. -f1)
  if [ "$NODE_MAJOR" -lt 18 ]; then
    check_fail "Node.js $NODE_VERSION too old (need >=18)" "Upgrade Node.js: nvm install 18"
  else
    check_ok "Node.js $NODE_VERSION"
  fi
fi

# npm
if command -v npm &>/dev/null; then
  NPM_VERSION=$(npm --version 2>/dev/null)
  check_ok "npm $NPM_VERSION"
else
  check_fail "npm not found" "Install npm (bundled with Node.js)"
fi

# openclaw CLI
if command -v openclaw &>/dev/null; then
  OC_VERSION=$(openclaw --version 2>/dev/null || echo "unknown")
  check_ok "openclaw CLI ($OC_VERSION)"
else
  check_fail "openclaw CLI not found" "Install openclaw: npm i -g openclaw"
fi

# Working directory
if [ -f "package.json" ]; then
  check_ok "Working directory: $ROOT_DIR"
else
  check_fail "Not in workspace root (no package.json)" "cd to workspace root"
fi

# Required directories
for dir in "test/baseline" "test/architecture" "scripts"; do
  if [ -d "$dir" ]; then
    check_ok "Directory exists: $dir"
  else
    check_fail "Directory missing: $dir" "Create $dir before running"
  fi
done

if $OVERALL_PASS; then
  ENV_PASS=true
  echo ""
  echo -e "  ${GREEN}Environment: PASS${NC}"
else
  ENV_PASS=false
  echo ""
  echo -e "  ${RED}Environment: FAIL${NC}"
fi

# ─────────────────────────────────────────────────────
# Step 2: Baseline Tests
# ─────────────────────────────────────────────────────
section "Step 2: Baseline Tests"

BASELINE_START=$(date +%s)

# Run baseline tests directly (not via buggy test-baseline.sh which has wrong TEST_DIR)
BASELINE_LOG=$(mktemp)
BASELINE_FILES=$(ls test/baseline/test-*.test.mjs 2>/dev/null || echo "")
BASELINE_TOTAL=$(echo "$BASELINE_FILES" | wc -w | tr -d ' ')

if [ -z "$BASELINE_FILES" ] || [ "$BASELINE_TOTAL" -eq 0 ]; then
  echo -e "  ${RED}✗${NC} No baseline test files found"
  fail_step "Baseline Tests" "No test files in test/baseline/" "Ensure PR-A baseline tests exist"
else
  echo "  Running $BASELINE_TOTAL baseline test files..."
  echo ""

  PASSED=0
  FAILED=0

  for f in $BASELINE_FILES; do
    name=$(basename "$f" .test.mjs)
    echo -ne "  [RUN ] $name ... "

    if node --test "$f" >> "$BASELINE_LOG" 2>&1; then
      echo -e "${GREEN}PASS${NC}"
      PASSED=$((PASSED + 1))
    else
      echo -e "${RED}FAIL${NC}"
      FAILED=$((FAILED + 1))
    fi
  done

  echo ""
  echo "  ──────────────────────────────────────────"
  echo "  Test files:  $BASELINE_TOTAL"
  echo "  Passed:      $PASSED"
  echo "  Failed:      $FAILED"
  echo "  Log:         $BASELINE_LOG"

  if [ "$FAILED" -gt 0 ]; then
    fail_step "Baseline Tests" "$FAILED/$BASELINE_TOTAL tests failed" "Check $BASELINE_LOG for details"
    BASELINE_PASS=false
  else
    BASELINE_PASS=true
  fi
fi

BASELINE_END=$(date +%s)
BASELINE_DURATION=$((BASELINE_END - BASELINE_START))
BASELINE_COUNT=$BASELINE_TOTAL

echo ""
echo -e "  Duration:    ${BASELINE_DURATION}s"
if $BASELINE_PASS; then
  echo -e "  ${GREEN}Baseline Tests: PASS${NC}"
else
  echo -e "  ${RED}Baseline Tests: FAIL${NC}"
fi

# ─────────────────────────────────────────────────────
# Step 3: Architecture Guards
# ─────────────────────────────────────────────────────
section "Step 3: Architecture Guards"

GUARD_SCRIPT="$SCRIPT_DIR/guard-all.sh"

if [ ! -f "$GUARD_SCRIPT" ]; then
  fail_step "Architecture Guard" "guard-all.sh not found at $GUARD_SCRIPT" "Ensure PR-B guard scripts exist"
  GUARD_PASS=false
else
  echo "  Running: bash $GUARD_SCRIPT"
  echo ""

  # Run guard-all but capture exit code — we need to differentiate HARD vs SOFT
  # guard-all.sh exits 1 if any hard guard fails
  GUARD_OUTPUT=$(bash "$GUARD_SCRIPT" 2>&1) || GUARD_EXIT=$?

  echo "$GUARD_OUTPUT"

  # Parse guard-all output for individual guard statuses
  GUARD_TOTAL=6
  GUARD_PASSED=0
  GUARD_FAILED=0
  GUARD_WARNED=0

  while IFS='|' read -r name result; do
    case "$result" in
      PASS) GUARD_PASSED=$((GUARD_PASSED + 1)) ;;
      FAIL) GUARD_FAILED=$((GUARD_FAILED + 1)) ;;
      WARN) GUARD_WARNED=$((GUARD_WARNED + 1)) ;;
    esac
  done < <(echo "$GUARD_OUTPUT" | grep -E '^\S+\|(PASS|FAIL|WARN)$' || true)

  # HARD guard failure = production check failure
  # SOFT guard warning ≠ production check failure
  if [ "${GUARD_EXIT:-0}" -ne 0 ]; then
    fail_step "Architecture Guard" "$GUARD_FAILED HARD guard(s) failed" "Review guard output above and fix violations"
    GUARD_PASS=false
  else
    GUARD_PASS=true
  fi

  echo ""
  echo "  Guard status: $GUARD_PASSED pass | $GUARD_FAILED fail | $GUARD_WARNED warn"

  if $GUARD_PASS; then
    echo -e "  ${GREEN}Architecture Guard: PASS${NC}"
  else
    echo -e "  ${RED}Architecture Guard: FAIL${NC}"
  fi
fi

# ─────────────────────────────────────────────────────
# Step 4: Deprecation Check
# ─────────────────────────────────────────────────────
section "Step 4: Deprecation Check"

DEPRECATION_SCRIPT="$SCRIPT_DIR/check-deprecations.mjs"

if [ ! -f "$DEPRECATION_SCRIPT" ]; then
  DEPRECATION_STATUS="FAIL"
  fail_step "Deprecation Check" "check-deprecations.mjs not found" "Ensure PR-C deprecation check script exists"
else
  echo "  Running: node $DEPRECATION_SCRIPT"
  echo ""

  # Deprecation check never fails on deprecation count, only on script crash
  DEPRECATION_OUTPUT=$(node "$DEPRECATION_SCRIPT" 2>&1) || DEP_EXIT=$?

  echo "$DEPRECATION_OUTPUT"

  # Extract deprecation count and list
  DEPRECATION_COUNT=$(echo "$DEPRECATION_OUTPUT" | grep "Total warnings:" | grep -oE '[0-9]+' || echo "0")
  
  if [ "${DEP_EXIT:-0}" -ne 0 ]; then
    DEPRECATION_STATUS="FAIL"
    fail_step "Deprecation Check" "Script crashed (exit $DEP_EXIT)" "Check $DEPRECATION_SCRIPT for errors"
  elif [ "$DEPRECATION_COUNT" -gt 0 ]; then
    DEPRECATION_STATUS="WARN"
  else
    DEPRECATION_STATUS="PASS"
  fi

  echo ""
  echo "  Deprecation items: $DEPRECATION_COUNT"

  # Print deprecation list if any
  DEP_LIST=$(echo "$DEPRECATION_OUTPUT" | sed -n '/Deprecated modules:/,/^$/p' || true)
  if [ -n "$DEP_LIST" ]; then
    echo "$DEP_LIST"
  fi

  case "$DEPRECATION_STATUS" in
    PASS) echo -e "  ${GREEN}Deprecation Check: PASS${NC}" ;;
    WARN) echo -e "  ${YELLOW}Deprecation Check: WARN${NC}" ;;
    FAIL) echo -e "  ${RED}Deprecation Check: FAIL${NC}" ;;
  esac
fi

# ─────────────────────────────────────────────────────
# Step 5: Smoke Test
# ─────────────────────────────────────────────────────
section "Step 5: Smoke Test"

SMOKE_SCRIPT="$SCRIPT_DIR/smoke-test.mjs"

if [ ! -f "$SMOKE_SCRIPT" ]; then
  fail_step "Smoke Test" "smoke-test.mjs not found at $SMOKE_SCRIPT" "Create scripts/smoke-test.mjs"
  SMOKE_PASS=false
else
  echo "  Running: node $SMOKE_SCRIPT"
  echo ""

  SMOKE_OUTPUT=$(node "$SMOKE_SCRIPT" 2>&1) || SMOKE_EXIT=$?

  echo "$SMOKE_OUTPUT"

  if [ "${SMOKE_EXIT:-0}" -eq 0 ]; then
    SMOKE_PASS=true
    echo -e "  ${GREEN}Smoke Test: PASS${NC}"
  else
    SMOKE_PASS=false
    fail_step "Smoke Test" "Smoke test failed (exit $SMOKE_EXIT)" "Check smoke test output above"
    echo -e "  ${RED}Smoke Test: FAIL${NC}"
  fi
fi

# ─────────────────────────────────────────────────────
# Step 6: Summary Report
# ─────────────────────────────────────────────────────
END_TIME=$(date +%s)
TOTAL_DURATION=$((END_TIME - START_TIME))

section "Step 6: Summary Report"

echo ""
echo -e "  ${BOLD}OpenClaw Production Check Summary${NC}"
echo -e "  ────────────────────────────────"

# Print each step status
print_status() {
  local label="$1" status="$2"
  case "$status" in
    PASS) echo -e "  ${label}: ${GREEN}PASS${NC}" ;;
    FAIL) echo -e "  ${label}: ${RED}FAIL${NC}" ;;
    WARN) echo -e "  ${label}: ${YELLOW}WARN${NC}" ;;
    *)    echo -e "  ${label}: $status" ;;
  esac
}

ENV_STR=$($ENV_PASS && echo "PASS" || echo "FAIL")
BASELINE_STR=$($BASELINE_PASS && echo "PASS" || echo "FAIL")
GUARD_STR=$($GUARD_PASS && echo "PASS" || echo "FAIL")

print_status "Environment"        "$ENV_STR"
print_status "Baseline Tests"     "$BASELINE_STR"
print_status "Architecture Guard" "$GUARD_STR"
print_status "Deprecation Check"  "$DEPRECATION_STATUS"
print_status "Smoke Test"         "$($SMOKE_PASS && echo "PASS" || echo "FAIL")"

echo ""
OVERALL_STR=$($OVERALL_PASS && echo "PASS" || echo "FAIL")
echo -e "  ${BOLD}Overall:${NC} $($OVERALL_PASS && echo -e "${GREEN}PASS${NC}" || echo -e "${RED}FAIL${NC}")"
echo -e "  ${BOLD}Duration:${NC} ${TOTAL_DURATION}s"

# Failure details
if ! $OVERALL_PASS; then
  echo ""
  echo -e "  ${RED}${BOLD}Failed Step:${NC} ${FAILED_STEP}"
  echo -e "  ${RED}${BOLD}Reason:${NC} ${FAIL_REASON}"
  echo -e "  ${YELLOW}${BOLD}Suggested Fix:${NC} ${FAIL_FIX}"
fi

echo ""
echo -e "${CYAN}══════════════════════════════════════════════${NC}"

if $OVERALL_PASS; then
  echo -e "${GREEN}  ✓ PRODUCTION CHECK PASSED — Safe to proceed${NC}"
  echo -e "${CYAN}══════════════════════════════════════════════${NC}"
  echo ""
  exit 0
else
  echo -e "${RED}  ✗ PRODUCTION CHECK FAILED — Fix before proceeding${NC}"
  echo -e "${CYAN}══════════════════════════════════════════════${NC}"
  echo ""
  exit 1
fi
