#!/usr/bin/env bash

set -euo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")/resources"

generate() {
	local name="$1"

	echo "=== BEGIN: $name"
	terraform init -upgrade &&
		terraform plan -out terraform.tfplan &&
		terraform show -json ./terraform.tfplan | jq >"$name".tfplan.json &&
		terraform graph -type=plan >"$name".tfplan.dot &&
		rm terraform.tfplan &&
		terraform apply -auto-approve &&
		terraform show -json ./terraform.tfstate | jq >"$name".tfstate.json &&
		rm terraform.tfstate &&
		terraform graph -type=plan >"$name".tfstate.dot
	ret=$?
	echo "=== END: $name"
	if [[ $ret -ne 0 ]]; then
		return $ret
	fi
}

minimize_diff() {
	for f in *.tf*.json; do
		declare -A deleted=()
		declare -a sed_args=()
		while read -r line; do
			# Deleted line (previous value).
			if [[ $line = -\ * ]]; then
				key="${line#*\"}"
				key="${key%%\"*}"
				value="${line#*: }"
				value="${value#*\"}"
				value="\"${value%\"*}\""
				declare deleted["$key"]="$value"
			# Added line (new value).
			elif [[ $line = +\ * ]]; then
				key="${line#*\"}"
				key="${key%%\"*}"
				value="${line#*: }"
				value="${value#*\"}"
				value="\"${value%\"*}\""
				# Matched key, restore the value.
				if [[ -v deleted["$key"] ]]; then
					sed_args+=(-e "s|${value}|${deleted["$key"]}|")
					unset "deleted[$key]"
				fi
			fi
			if [[ ${#sed_args[@]} -gt 0 ]]; then
				# Handle macOS compat.
				if grep -q -- "\[-i extension\]" < <(sed -h 2>&1); then
					sed -i '' "${sed_args[@]}" "$f"
				else
					sed -i'' "${sed_args[@]}" "$f"
				fi
			fi
		done < <(
			# Filter out known keys with autogenerated values.
			git diff -- "$f" |
				grep -E "\"(terraform_version|id|agent_id|resource_id|token|random|timestamp)\":"
		)
	done
}

run() {
	d="$1"
	cd "$d"
	name=$(basename "$(pwd)")

	toskip=(
		# This needs care to update correctly.
		"kubernetes-metadata"
	)
	for skip in "${toskip[@]}"; do
		if [[ $name == "$skip" ]]; then
			echo "== Skipping: $name"
			touch "$name.tfplan.json" "$name.tfplan.dot" "$name.tfstate.json" "$name.tfstate.dot"
			return 0
		fi
	done

	echo "== Generating test data for: $name"
	if ! out="$(generate "$name" 2>&1)"; then
		echo "$out"
		echo "== Error generating test data for: $name"
		return 1
	fi
	if ((minimize)); then
		echo "== Minimizing diffs for: $name"
		minimize_diff
	fi
	echo "== Done generating test data for: $name"
	exit 0
}

if [[ " $* " == *" --help "* || " $* " == *" -h "* ]]; then
	echo "Usage: $0 [module1 module2 ...]"
	exit 0
fi

minimize=1
if [[ " $* " == *" --no-minimize "* ]]; then
	minimize=0
fi

declare -a jobs=()
if [[ $# -gt 0 ]]; then
	for d in "$@"; do
		run "$d" &
		jobs+=($!)
	done
else
	for d in */; do
		run "$d" &
		jobs+=($!)
	done
fi

err=0
for job in "${jobs[@]}"; do
	if ! wait "$job"; then
		err=$((err + 1))
	fi
done
if [[ $err -ne 0 ]]; then
	echo "ERROR: Failed to generate test data for $err modules"
	exit 1
fi

terraform version -json | jq -r '.terraform_version' >version.txt
