#!/usr/bin/env bash
# fleet/apply.sh — real convergence, ONE role at a time, gated fail-closed on
# a fresh reviewed check-diff artifact. There is no all-roles apply by
# design: an apply without a stored, read diff is impossible by construction.
#
# usage: fleet/apply.sh <role> [--limit <group-or-host>] [extra ansible-playbook args]
#   role must be one of: path_bins | settings_template | systemd_units
#
# Before running: fleet/check.sh --tags <role>, read the diff artifact it
# writes to fleet/reports/, confirm it matches expectations (including the
# fold-forward rule — a diff that would revert a known-good live fix means
# STOP and adopt the live value into source instead of applying).
set -euo pipefail

FLEET_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
role="${1:-}"
shift || true

case "$role" in
  path_bins|settings_template|systemd_units) ;;
  *)
    echo "fleet/apply.sh: ERROR: usage: fleet/apply.sh <path_bins|settings_template|systemd_units> [--limit ...]" >&2
    exit 2
    ;;
esac

for arg in "$@"; do
  case "$arg" in
    --check|-C) echo "fleet/apply.sh: ERROR: --check/-C makes this a no-op apply; use fleet/check.sh instead" >&2; exit 2 ;;
  esac
done

latest_artifact=$(ls -t "$FLEET_DIR/reports/"check-*-"${role}".txt 2>/dev/null | head -1 || true)
if [[ -z "$latest_artifact" ]]; then
  echo "fleet/apply.sh: ERROR: no check-diff artifact for role '$role' in fleet/reports/." >&2
  echo "Run: fleet/check.sh --tags $role   (and save its output there) before applying." >&2
  exit 1
fi

artifact_age_sec=$(( $(date +%s) - $(date -r "$latest_artifact" +%s) ))
max_age_sec=$(( 60 * 60 * 4 ))  # 4h: an apply must follow a genuinely fresh diff read, not a stale one
if (( artifact_age_sec > max_age_sec )); then
  echo "fleet/apply.sh: ERROR: $latest_artifact is $((artifact_age_sec/60))min old (>${max_age_sec}s max)." >&2
  echo "Re-run fleet/check.sh --tags $role and re-read the diff before applying." >&2
  exit 1
fi

echo "fleet/apply.sh: applying role '$role', gated on $latest_artifact (age ${artifact_age_sec}s)" >&2

export LANG="${LANG:-C.UTF-8}"
export LC_ALL="${LC_ALL:-C.UTF-8}"
ANSIBLE_PLAYBOOK="${ANSIBLE_PLAYBOOK_BIN:-ansible-playbook}"

bash "$FLEET_DIR/gen-inventory.sh"

exec "$ANSIBLE_PLAYBOOK" \
  -i "$FLEET_DIR/inventory.yml" \
  "$FLEET_DIR/site.yml" \
  --tags "$role" \
  --diff \
  "$@"
