#!/bin/bash
# Health check script for blue-green deployment
# Verifies container health and HTTP endpoints
#
# Usage: ./health-check.sh <stack> [timeout_seconds]
#   stack: blue or green
#   timeout_seconds: max wait time (default: 60)
#
# Exit codes:
#   0 - All health checks passed
#   1 - Health check failed

set -euo pipefail

# Use DEPLOY_PATH if set (CI environment), otherwise calculate from script location
PROJECT_ROOT="${DEPLOY_PATH:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"

echo "Using PROJECT_ROOT: $PROJECT_ROOT"

STACK="${1:-}"
TIMEOUT="${2:-60}"

if [[ -z "$STACK" ]] || [[ ! "$STACK" =~ ^(blue|green)$ ]]; then
  echo "Usage: $0 <blue|green> [timeout_seconds]"
  exit 1
fi

FRONTEND_CONTAINER="mvp-frontend-$STACK"
BACKEND_CONTAINER="mvp-backend-$STACK"

echo "========================================"
echo "Health Check - $STACK Stack"
echo "Timeout: ${TIMEOUT}s"
echo "========================================"

# Function to check Docker container health
check_container_health() {
  local container="$1"
  local status

  status=$(docker inspect --format='{{.State.Health.Status}}' "$container" 2>/dev/null || echo "not found")

  case "$status" in
    "healthy")
      return 0
      ;;
    "starting")
      return 2  # Still starting
      ;;
    "unhealthy"|"not found"|"")
      return 1
      ;;
    *)
      return 1
      ;;
  esac
}

# Function to check HTTP endpoint
check_http_endpoint() {
  local container="$1"
  local port="$2"
  local path="$3"

  if docker exec "$container" curl -sf "http://localhost:${port}${path}" > /dev/null 2>&1; then
    return 0
  else
    return 1
  fi
}

# Function to check database connectivity via backend
check_database_connectivity() {
  local container="$1"

  # The /health endpoint should verify database connectivity
  if docker exec "$container" curl -sf "http://localhost:3001/health" 2>/dev/null | grep -q '"database"'; then
    return 0
  else
    return 1
  fi
}

# Wait for containers to be healthy
wait_for_health() {
  local container="$1"
  local elapsed=0

  while [[ $elapsed -lt $TIMEOUT ]]; do
    check_container_health "$container"
    local status=$?

    if [[ $status -eq 0 ]]; then
      return 0
    fi

    # Both "starting" and "unhealthy" are treated as transient during the wait period.
    # Docker can report "unhealthy" briefly during start_period before the next check
    # cycle transitions it back. Only the overall timeout should cause failure.
    sleep 2
    elapsed=$((elapsed + 2))
    echo "  Waiting for $container... (${elapsed}s/${TIMEOUT}s)"
  done

  echo "  ERROR: Container $container did not become healthy within ${TIMEOUT}s"
  docker logs "$container" --tail 20 2>/dev/null || true
  return 1
}

# Main health check sequence
echo ""
echo "Step 1/4: Checking container status..."
echo "----------------------------------------"

for container in "$FRONTEND_CONTAINER" "$BACKEND_CONTAINER"; do
  running=$(docker inspect --format='{{.State.Running}}' "$container" 2>/dev/null || echo "false")
  if [[ "$running" != "true" ]]; then
    echo "  ERROR: Container $container is not running"
    docker ps -a --filter "name=$container" --format "table {{.Names}}\t{{.Status}}"
    exit 1
  fi
  echo "  OK: $container is running"
done

echo ""
echo "Step 2/4: Waiting for Docker health checks..."
echo "----------------------------------------"

for container in "$FRONTEND_CONTAINER" "$BACKEND_CONTAINER"; do
  echo "  Checking $container..."
  if ! wait_for_health "$container"; then
    echo "  FAILED: $container health check"
    exit 1
  fi
  echo "  OK: $container is healthy"
done

echo ""
echo "Step 3/4: Verifying HTTP endpoints..."
echo "----------------------------------------"

# Check frontend
echo "  Checking frontend HTTP..."
if ! check_http_endpoint "$FRONTEND_CONTAINER" 3000 "/"; then
  echo "  FAILED: Frontend HTTP check"
  exit 1
fi
echo "  OK: Frontend responds on port 3000"

# Check backend health endpoint
echo "  Checking backend HTTP..."
if ! check_http_endpoint "$BACKEND_CONTAINER" 3001 "/health"; then
  echo "  FAILED: Backend HTTP check"
  exit 1
fi
echo "  OK: Backend responds on port 3001"

echo ""
echo "Step 4/4: Verifying database connectivity..."
echo "----------------------------------------"

if ! check_database_connectivity "$BACKEND_CONTAINER"; then
  echo "  WARNING: Could not verify database connectivity"
  echo "  (Backend may not expose database status in /health)"
else
  echo "  OK: Database connectivity verified"
fi

echo ""
echo "========================================"
echo "Health Check PASSED - $STACK Stack"
echo "========================================"

# Update state file
STATE_FILE="$PROJECT_ROOT/config/deployment/state.json"
if [[ -f "$STATE_FILE" ]]; then
  # Update stack health status using jq if available
  if command -v jq &> /dev/null; then
    TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
    jq --arg stack "$STACK" --arg ts "$TIMESTAMP" \
      '.[$stack].healthy = true | .[$stack].last_health_check = $ts' \
      "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
  fi
fi

exit 0
