#!/usr/bin/env bash
# =============================================================================
# Changemaker Lite — Compose Parity Validator
#
# The dev (docker-compose.yml) and prod (docker-compose.prod.yml) files share
# ~95% of their service definitions verbatim, but there is no tooling that
# ensures they stay in sync. A drift in healthcheck tolerances between them
# can cause release-tarball installs to silently fail where dev installs pass
# (or vice versa).
#
# This script compares the `healthcheck:` block for a fixed set of critical
# services between the two files and exits non-zero if any of them diverge.
#
# Run manually: bash scripts/validate-compose-parity.sh
# Also invoked by scripts/build-release.sh before packaging the tarball.
# =============================================================================
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
DEV_FILE="${PROJECT_DIR}/docker-compose.yml"
PROD_FILE="${PROJECT_DIR}/docker-compose.prod.yml"

# Services whose healthcheck must be identical across dev and prod.
CRITICAL_SERVICES=(api media-api admin nginx)

if [[ ! -f "$DEV_FILE" ]] || [[ ! -f "$PROD_FILE" ]]; then
  echo "ERROR: Could not find both compose files (expected $DEV_FILE and $PROD_FILE)" >&2
  exit 2
fi

# Extract the healthcheck block for a given service from a compose file.
# Uses awk to walk indentation: find `^  <service>:`, then within it the
# `    healthcheck:` block, and print the healthcheck lines until a sibling
# key (same 4-space indent) or end of service.
extract_healthcheck() {
  local file="$1" service="$2"
  awk -v svc="$service" '
    # Entering the target service definition?
    $0 ~ "^  "svc":[[:space:]]*$" { in_svc=1; next }
    # Next top-level service — stop scanning
    in_svc && /^  [a-zA-Z0-9_-]+:[[:space:]]*$/ { in_svc=0 }
    # Inside target service, watch for healthcheck block
    in_svc && /^    healthcheck:[[:space:]]*$/ { in_hc=1; print; next }
    # Inside healthcheck: print until we hit a sibling key at same indent
    in_hc {
      if (/^    [a-zA-Z0-9_-]+:/) { in_hc=0 }
      else { print }
    }
  ' "$file"
}

FAIL=0
for svc in "${CRITICAL_SERVICES[@]}"; do
  dev_hc="$(extract_healthcheck "$DEV_FILE" "$svc")"
  prod_hc="$(extract_healthcheck "$PROD_FILE" "$svc")"

  if [[ -z "$dev_hc" ]] && [[ -z "$prod_hc" ]]; then
    continue  # service not defined in either — fine (e.g. media-api optional)
  fi

  if [[ "$dev_hc" != "$prod_hc" ]]; then
    echo "DRIFT: healthcheck block for service '${svc}' differs between dev and prod compose files" >&2
    echo "--- $(basename "$DEV_FILE")" >&2
    echo "$dev_hc" >&2
    echo "--- $(basename "$PROD_FILE")" >&2
    echo "$prod_hc" >&2
    echo "" >&2
    FAIL=1
  fi
done

if [[ "$FAIL" -ne 0 ]]; then
  echo "Compose parity check FAILED. Update both files before releasing." >&2
  exit 1
fi

echo "Compose parity: OK (${#CRITICAL_SERVICES[@]} services checked)"
