#!/usr/bin/env bash
#MISE description="terragrunt apply for a prod deployment stack (builds providers, escalates to the write SA, renders creds from 1Password). SITE selects the stack."
set -euo pipefail
ROOT=$(git rev-parse --show-toplevel)

# OpenTofu's Go binary doesn't read the macOS keychain, so the OVH S3 backend's
# cert fails to verify locally ("unknown authority"). Point it at the system CA
# bundle on macOS; Linux/CI reads its trust store fine and is left alone.
if [ -z "${SSL_CERT_FILE:-}" ] && [ "$(uname -s)" = "Darwin" ] && [ -f /etc/ssl/cert.pem ]; then
  export SSL_CERT_FILE=/etc/ssl/cert.pem AWS_CA_BUNDLE=/etc/ssl/cert.pem
fi

mise run infra:providers

# Escalate to the write-capable service-account token, which is itself stored in
# the vault: CI hands us a read-scoped token in OP_SERVICE_ACCOUNT_TOKEN (locally
# we sign in to team-futo), and we use it to read the write SA, then run the apply
# as that SA so the onepassword provider can create/update items. One GitHub
# secret (the read token) is enough; the write privilege lives in 1Password.
ACCT=(); [ -z "${OP_SERVICE_ACCOUNT_TOKEN:-}" ] && ACCT=(--account "${OP_ACCOUNT:-team-futo}")
OP_SERVICE_ACCOUNT_TOKEN=$(op read "${ACCT[@]}" \
  "op://yucca_tf_prod/yucca_futo_1pass_service_account_write/password")
export OP_SERVICE_ACCOUNT_TOKEN

# Render the NETCONF SSH key from 1Password to a 0600 temp file (op run can't
# write files) — now via the escalated SA.
KEYF=$(mktemp); chmod 600 "$KEYF"; trap 'rm -f "$KEYF"' EXIT
op read "op://yucca_tf_prod/NET_SWITCHES_TERRAFORM_SSH_PRIVATE_KEY/password" > "$KEYF"

export TF_VAR_netconf_ssh_key_path="$KEYF"
export TF_CLI_CONFIG_FILE="$ROOT/tf/.terraformrc.local"
SITE="${SITE:-htz-fsn1}"
# With a service-account token in the env, drop OP_ACCOUNT — the onepassword
# provider rejects having both set ("service_account_token and account are set").
unset OP_ACCOUNT
STACK_DIR="tf/deployment/prod/$SITE/fabric"

# Bind the apply to the reviewed plan. When CI passes TG_PLAN pointing at the
# saved plan artifact, apply THAT file (no fresh re-plan, no -auto-approve): tofu
# fails closed if the saved plan is stale relative to current state. Strip any
# -auto-approve the caller passed (meaningless with a plan file). Local/manual
# runs leave TG_PLAN unset and keep the interactive/`-auto-approve` behaviour.
APPLY_ARGS=("$@")
if [ -n "${TG_PLAN:-}" ]; then
  [ -f "$TG_PLAN" ] || { echo "infra:apply: TG_PLAN set but plan file missing: $TG_PLAN" >&2; exit 1; }
  filtered=(); for a in "${APPLY_ARGS[@]}"; do [ "$a" = "-auto-approve" ] && continue; filtered+=("$a"); done
  APPLY_ARGS=("${filtered[@]}" "$TG_PLAN")
fi

# jeremmfr/junos is concurrency-safe (per-resource CRUD); reads/refresh run in
# parallel and commits serialize on the per-device config lock (handled by the
# provider). The device NETCONF connection-limit is raised to 250.
OP_ENV_FILE=tf/.env.prod "$ROOT/tf/op-run.sh" terragrunt --working-dir "$STACK_DIR" apply -parallelism=4 "${APPLY_ARGS[@]}"

# Confirm the dangling `commit confirmed` jeremmfr leaves on the last commit per
# device: its per-resource "confirm" is `commit check`, which does NOT cancel the
# rollback on our Junos, so without this the last change auto-reverts. A plain
# `commit` confirms it. This runs ONLY after a successful apply (set -e): a
# mgmt-breaking apply errors above and skips this, so the dangling commit rolls
# back and restores management. Nothing pending → `commit` is a harmless no-op.
echo "==> confirming commit-confirmed on managed switches"
IPS=$(OP_ENV_FILE=tf/.env.prod "$ROOT/tf/op-run.sh" terragrunt --working-dir "$STACK_DIR" output -json switch_mgmt_ips | tr -d '[]" ' | tr ',' '\n')
KH=$(mktemp); trap 'rm -f "$KEYF" "$KH"' EXIT
for ip in $IPS; do
  [ -n "$ip" ] || continue
  ok=
  for attempt in 1 2 3; do
    if ssh -i "$KEYF" -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new \
         -o UserKnownHostsFile="$KH" -o ConnectTimeout=15 -o NumberOfPasswordPrompts=0 \
         -o BatchMode=yes "terraform@$ip" "configure; commit; exit" >/dev/null 2>&1; then
      ok=1; echo "    confirmed $ip"; break
    fi
    echo "    confirm attempt $attempt failed on $ip; retrying..."; sleep 5
  done
  [ -n "$ok" ] || { echo "ERROR: could not confirm commit on $ip — its last change will roll back (commit_confirmed). Investigate." >&2; exit 1; }
done
