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

BASE_URL="${1:-http://localhost:8080}"
ACTUATOR_BASE_URL="${ACTUATOR_BASE_URL:-$BASE_URL}"
PASS=0
FAIL=0
TMP_DIR="$(mktemp -d)"
COOKIE_JAR="$TMP_DIR/cookies"
USERNAME="smoketest_$(date +%s)"
EMAIL="${USERNAME}@example.com"
PASSWORD="Smoke@2026"
NEW_PASSWORD="Smoke@2027"

cleanup() {
  rm -rf "$TMP_DIR"
}

trap cleanup EXIT

check() {
  local desc="$1"
  local url="$2"
  local expected="$3"
  local status
  status="$(curl --retry 3 --retry-delay 1 --max-time 10 -s -o /dev/null -w "%{http_code}" "$url" || true)"
  if [[ "$status" == "$expected" ]]; then
    echo "PASS: $desc (HTTP $status)"
    PASS=$((PASS + 1))
  else
    echo "FAIL: $desc (expected $expected, got $status)"
    FAIL=$((FAIL + 1))
  fi
}

check_health() {
  local desc="$1"
  local url="$2"
  local body_file="$TMP_DIR/health-body"
  local result
  local status
  local content_type
  result="$(curl --retry 3 --retry-delay 1 --max-time 10 -sS -o "$body_file" \
    -w "%{http_code}|%{content_type}" "$url" || true)"
  status="${result%%|*}"
  content_type="${result#*|}"

  if [[ "$content_type" == text/html* ]]; then
    echo "FAIL: $desc (routing/target error: received $content_type from $url)"
    FAIL=$((FAIL + 1))
  elif [[ "$status" == "200" \
    && ( "$content_type" == application/json* || "$content_type" == application/*+json* ) \
    && -f "$body_file" \
    && "$(grep -Ec '"status"[[:space:]]*:' "$body_file" || true)" -gt 0 ]]; then
    echo "PASS: $desc (HTTP $status, $content_type)"
    PASS=$((PASS + 1))
  else
    echo "FAIL: $desc (expected HTTP 200 actuator JSON, got HTTP $status, ${content_type:-no content type})"
    FAIL=$((FAIL + 1))
  fi
}

check_protected_actuator() {
  local desc="$1"
  local url="$2"
  local result
  local status
  local content_type
  result="$(curl --retry 3 --retry-delay 1 --max-time 10 -sS -o /dev/null \
    -w "%{http_code}|%{content_type}" "$url" || true)"
  status="${result%%|*}"
  content_type="${result#*|}"

  if [[ "$content_type" == text/html* ]]; then
    echo "FAIL: $desc (routing/target error: received $content_type from $url)"
    FAIL=$((FAIL + 1))
  elif [[ "$status" == "401" ]]; then
    echo "PASS: $desc (HTTP $status)"
    PASS=$((PASS + 1))
  else
    echo "FAIL: $desc (expected 401, got $status)"
    FAIL=$((FAIL + 1))
  fi
}

finish() {
  echo
  echo "Results: $PASS passed, $FAIL failed"
  [[ "$FAIL" -eq 0 ]]
}

echo "=== SkillHub Smoke Test ==="
echo "API target: $BASE_URL"
echo "Actuator target: $ACTUATOR_BASE_URL"
echo

check_health "Health endpoint" "$ACTUATOR_BASE_URL/actuator/health"
check_protected_actuator "Prometheus metrics requires auth" "$ACTUATOR_BASE_URL/actuator/prometheus"
check "Namespaces API requires auth" "$BASE_URL/api/v1/namespaces" "401"
check "Auth required" "$BASE_URL/api/v1/auth/me" "401"

curl -s -c "$COOKIE_JAR" "$BASE_URL/api/v1/auth/me" >/dev/null
CSRF_TOKEN="$(awk '$6 == "XSRF-TOKEN" { print $7 }' "$COOKIE_JAR" | tail -n 1)"

REGISTER_STATUS="$(curl --max-time 10 -s -o /dev/null -w "%{http_code}" \
  -X POST "$BASE_URL/api/v1/auth/local/register" \
  -b "$COOKIE_JAR" \
  -c "$COOKIE_JAR" \
  -H "X-XSRF-TOKEN: $CSRF_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"username\":\"$USERNAME\",\"password\":\"$PASSWORD\",\"email\":\"$EMAIL\"}" || true)"
if [[ "$REGISTER_STATUS" == "200" ]]; then
  echo "PASS: Register (HTTP $REGISTER_STATUS)"
  PASS=$((PASS + 1))
else
  echo "FAIL: Register (got $REGISTER_STATUS)"
  FAIL=$((FAIL + 1))
fi

AUTH_ME_STATUS="$(curl --max-time 10 -s -o /dev/null -w "%{http_code}" -b "$COOKIE_JAR" "$BASE_URL/api/v1/auth/me" || true)"
if [[ "$AUTH_ME_STATUS" == "200" ]]; then
  echo "PASS: Auth me with session (HTTP $AUTH_ME_STATUS)"
  PASS=$((PASS + 1))
else
  echo "FAIL: Auth me with session (got $AUTH_ME_STATUS)"
  FAIL=$((FAIL + 1))
fi

NAMESPACES_AUTH_STATUS="$(curl --max-time 10 -s -o /dev/null -w "%{http_code}" -b "$COOKIE_JAR" "$BASE_URL/api/v1/namespaces" || true)"
if [[ "$NAMESPACES_AUTH_STATUS" == "200" ]]; then
  echo "PASS: Namespaces API with session (HTTP $NAMESPACES_AUTH_STATUS)"
  PASS=$((PASS + 1))
else
  echo "FAIL: Namespaces API with session (got $NAMESPACES_AUTH_STATUS)"
  FAIL=$((FAIL + 1))
fi

CHANGE_PASSWORD_STATUS="$(curl --max-time 10 -s -o /dev/null -w "%{http_code}" \
  -X POST "$BASE_URL/api/v1/auth/local/change-password" \
  -b "$COOKIE_JAR" \
  -H "X-XSRF-TOKEN: $CSRF_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"currentPassword\":\"$PASSWORD\",\"newPassword\":\"$NEW_PASSWORD\"}" || true)"
if [[ "$CHANGE_PASSWORD_STATUS" == "200" ]]; then
  echo "PASS: Change password (HTTP $CHANGE_PASSWORD_STATUS)"
  PASS=$((PASS + 1))
else
  echo "FAIL: Change password (got $CHANGE_PASSWORD_STATUS)"
  FAIL=$((FAIL + 1))
fi

LOGOUT_STATUS="$(curl --max-time 10 -s -o /dev/null -w "%{http_code}" \
  -X POST "$BASE_URL/api/v1/auth/logout" \
  -b "$COOKIE_JAR" \
  -c "$COOKIE_JAR" \
  -H "X-XSRF-TOKEN: $CSRF_TOKEN" || true)"
if [[ "$LOGOUT_STATUS" == "302" || "$LOGOUT_STATUS" == "200" || "$LOGOUT_STATUS" == "204" ]]; then
  echo "PASS: Logout (HTTP $LOGOUT_STATUS)"
  PASS=$((PASS + 1))
else
  echo "FAIL: Logout (got $LOGOUT_STATUS)"
  FAIL=$((FAIL + 1))
fi

POST_LOGOUT_STATUS="$(curl --max-time 10 -s -o /dev/null -w "%{http_code}" -b "$COOKIE_JAR" "$BASE_URL/api/v1/auth/me" || true)"
if [[ "$POST_LOGOUT_STATUS" == "401" ]]; then
  echo "PASS: Auth me after logout (HTTP $POST_LOGOUT_STATUS)"
  PASS=$((PASS + 1))
else
  echo "FAIL: Auth me after logout (got $POST_LOGOUT_STATUS)"
  FAIL=$((FAIL + 1))
fi

# ---- Label Management (requires admin) ----
SMOKE_ADMIN_CHECKS="${SMOKE_ADMIN_CHECKS:-auto}"
SMOKE_ADMIN_USERNAME="${SMOKE_ADMIN_USERNAME:-}"
SMOKE_ADMIN_PASSWORD="${SMOKE_ADMIN_PASSWORD:-}"
ADMIN_CONFIG_FAILED=0
if [[ "$SMOKE_ADMIN_CHECKS" != "auto" && "$SMOKE_ADMIN_CHECKS" != "true" && "$SMOKE_ADMIN_CHECKS" != "false" ]]; then
  echo "FAIL: SMOKE_ADMIN_CHECKS must be auto, true, or false"
  FAIL=$((FAIL + 1))
  ADMIN_CONFIG_FAILED=1
fi
if [[ "$SMOKE_ADMIN_CHECKS" == "true" && ( -z "$SMOKE_ADMIN_USERNAME" || -z "$SMOKE_ADMIN_PASSWORD" ) ]]; then
  echo "FAIL: SMOKE_ADMIN_CHECKS=true requires SMOKE_ADMIN_USERNAME and SMOKE_ADMIN_PASSWORD"
  FAIL=$((FAIL + 1))
  ADMIN_CONFIG_FAILED=1
fi
if [[ "$ADMIN_CONFIG_FAILED" -ne 0 ]]; then
  finish
  exit $?
fi
if [[ "$SMOKE_ADMIN_CHECKS" == "false" || ( "$SMOKE_ADMIN_CHECKS" == "auto" && ( -z "$SMOKE_ADMIN_USERNAME" || -z "$SMOKE_ADMIN_PASSWORD" ) ) ]]; then
  echo "SKIP: Admin label management (set SMOKE_ADMIN_USERNAME and SMOKE_ADMIN_PASSWORD to enable)"
  finish
  exit $?
fi

ADMIN_COOKIE_JAR="$(mktemp)"
LABEL_SLUG="smoke-label-$(date +%s)"

cleanup_admin() {
  rm -f "$ADMIN_COOKIE_JAR"
}
trap 'cleanup; cleanup_admin' EXIT

# Get CSRF token for admin session
curl -s -c "$ADMIN_COOKIE_JAR" "$BASE_URL/api/v1/auth/me" >/dev/null
ADMIN_CSRF="$(awk '$6 == "XSRF-TOKEN" { print $7 }' "$ADMIN_COOKIE_JAR" | tail -n 1)"

# Login as admin
ADMIN_LOGIN_STATUS="$(curl --max-time 10 -s -o /dev/null -w "%{http_code}" \
  -X POST "$BASE_URL/api/v1/auth/local/login" \
  -b "$ADMIN_COOKIE_JAR" \
  -c "$ADMIN_COOKIE_JAR" \
  -H "X-XSRF-TOKEN: $ADMIN_CSRF" \
  -H "Content-Type: application/json" \
  -d "{\"username\":\"$SMOKE_ADMIN_USERNAME\",\"password\":\"$SMOKE_ADMIN_PASSWORD\"}" || true)"
if [[ "$ADMIN_LOGIN_STATUS" == "200" ]]; then
  echo "PASS: Admin login (HTTP $ADMIN_LOGIN_STATUS)"
  PASS=$((PASS + 1))
else
  echo "FAIL: Admin login (got $ADMIN_LOGIN_STATUS)"
  FAIL=$((FAIL + 1))
fi

# Refresh CSRF after login
ADMIN_CSRF="$(awk '$6 == "XSRF-TOKEN" { print $7 }' "$ADMIN_COOKIE_JAR" | tail -n 1)"

# Create label definition
CREATE_LABEL_STATUS="$(curl --max-time 10 -s -o /dev/null -w "%{http_code}" \
  -X POST "$BASE_URL/api/v1/admin/labels" \
  -b "$ADMIN_COOKIE_JAR" \
  -H "X-XSRF-TOKEN: $ADMIN_CSRF" \
  -H "Content-Type: application/json" \
  -d "{\"slug\":\"$LABEL_SLUG\",\"type\":\"RECOMMENDED\",\"visibleInFilter\":true,\"sortOrder\":99,\"translations\":[{\"locale\":\"en\",\"displayName\":\"Smoke Label\"}]}" || true)"
if [[ "$CREATE_LABEL_STATUS" == "200" ]]; then
  echo "PASS: Create label definition (HTTP $CREATE_LABEL_STATUS)"
  PASS=$((PASS + 1))
else
  echo "FAIL: Create label definition (got $CREATE_LABEL_STATUS)"
  FAIL=$((FAIL + 1))
fi

# List admin label definitions
LIST_LABELS_STATUS="$(curl --max-time 10 -s -o /dev/null -w "%{http_code}" \
  -b "$ADMIN_COOKIE_JAR" "$BASE_URL/api/v1/admin/labels" || true)"
if [[ "$LIST_LABELS_STATUS" == "200" ]]; then
  echo "PASS: List admin label definitions (HTTP $LIST_LABELS_STATUS)"
  PASS=$((PASS + 1))
else
  echo "FAIL: List admin label definitions (got $LIST_LABELS_STATUS)"
  FAIL=$((FAIL + 1))
fi

# List visible labels (public)
VISIBLE_LABELS_STATUS="$(curl --max-time 10 -s -o /dev/null -w "%{http_code}" \
  "$BASE_URL/api/v1/labels" || true)"
if [[ "$VISIBLE_LABELS_STATUS" == "200" ]]; then
  echo "PASS: List visible labels (HTTP $VISIBLE_LABELS_STATUS)"
  PASS=$((PASS + 1))
else
  echo "FAIL: List visible labels (got $VISIBLE_LABELS_STATUS)"
  FAIL=$((FAIL + 1))
fi

# Delete label definition (cleanup)
DELETE_LABEL_STATUS="$(curl --max-time 10 -s -o /dev/null -w "%{http_code}" \
  -X DELETE "$BASE_URL/api/v1/admin/labels/$LABEL_SLUG" \
  -b "$ADMIN_COOKIE_JAR" \
  -H "X-XSRF-TOKEN: $ADMIN_CSRF" || true)"
if [[ "$DELETE_LABEL_STATUS" == "200" || "$DELETE_LABEL_STATUS" == "204" ]]; then
  echo "PASS: Delete label definition (HTTP $DELETE_LABEL_STATUS)"
  PASS=$((PASS + 1))
else
  echo "FAIL: Delete label definition (got $DELETE_LABEL_STATUS)"
  FAIL=$((FAIL + 1))
fi

finish
