TF_BACKEND_INIT_STACK_NAME := tf-backend-init
STATE_BUCKET_NAME := flw-iac-tf-state
STATE_LOG_BUCKET_NAME := flw-iac-tf-state-logs
LOCK_TABLE_NAME := flw-iac-tf-state-locks

# Use a known profile to ensure account ID is correct
SECURITY_ACCOUNT_ID := $(shell \
	aws --profile ${AWS_CLI_SEC_PROFILE} sts get-caller-identity | jq -r .Account \
)

TF_BACKEND_ROLE_PATH := terraform/TerraformBackend
TF_BACKEND_ROLE_ARN := arn:aws:iam::${SECURITY_ACCOUNT_ID}:role/${TF_BACKEND_ROLE_PATH}

SEC_IAM_INIT_STACK_NAME := sec-iam-init
SEC_SECRET_INIT_STACK_NAME := sec-secrets-init

DEPLOYMENT_DIRS := $(shell find . -name terragrunt.hcl \
	-not -path */.terragrunt-cache/* -exec dirname {} \; \
)

CFN := aws cloudformation --profile ${AWS_CLI_PROD_PROFILE}
CFN_START_DRIFT_DETECTION := $(CFN) detect-stack-drift --stack-name
CFN_STATUS_DRIFT_DETECTION := $(CFN) describe-stack-drift-detection-status \
	--stack-drift-detection-id

define wait_cfn_drift_detect_job
	@while [[ \
		"$$($(CFN_STATUS_DRIFT_DETECTION) $(1) | jq -r .DetectionStatus)" == \
		"DETECTION_IN_PROGRESS" \
	]]; do \
		echo "Detection in progress. Waiting 3 seconds..."; \
		sleep 3; \
	done
endef

define show_cfn_drift
	$(eval DRIFT_ID=$(shell $(CFN_START_DRIFT_DETECTION) $(1) \
		| jq -r .StackDriftDetectionId))
	$(call wait_cfn_drift_detect_job,${DRIFT_ID})
	@$(CFN_STATUS_DRIFT_DETECTION) $(DRIFT_ID) | jq '{ \
		DetectionStatus, \
		StackDriftStatus, \
		DriftedStackResourceCount \
	}'
endef

.PHONY: init-tf-backend
init-tf-backend:
	aws cloudformation deploy \
		--profile ${AWS_CLI_SEC_PROFILE} \
		--template-file init-tf-backend.cf.yml \
		--stack-name ${TF_BACKEND_INIT_STACK_NAME} \
		--capabilities CAPABILITY_NAMED_IAM \
		--parameter-overrides \
			SecurityAccountId=${SECURITY_ACCOUNT_ID} \
			StateBucketName=${STATE_BUCKET_NAME} \
			StateLogBucketName=${STATE_LOG_BUCKET_NAME} \
			LockTableName=${LOCK_TABLE_NAME}
	aws cloudformation update-termination-protection \
		--profile ${AWS_CLI_SEC_PROFILE} \
		--stack-name ${TF_BACKEND_INIT_STACK_NAME} \
		--enable-termination-protection

.PHONY: init-security-iam
init-security-iam:
	aws cloudformation deploy \
		--profile ${AWS_CLI_SEC_PROFILE} \
		--template-file init-iam.cf.yml \
		--stack-name ${SEC_IAM_INIT_STACK_NAME} \
		--capabilities CAPABILITY_NAMED_IAM \
		--parameter-overrides \
			SecurityAccountId=${SECURITY_ACCOUNT_ID} \
			TerraformBackendRoleARN=${TF_BACKEND_ROLE_ARN} \
			DevAccountId=${DEV_ACCOUNT_ID} \
			ProdAccountId=${PROD_ACCOUNT_ID}
	aws cloudformation update-termination-protection \
		--profile ${AWS_CLI_SEC_PROFILE} \
		--stack-name ${SEC_IAM_INIT_STACK_NAME} \
		--enable-termination-protection

.PHONY: init-security-secrets
init-security-secrets:
	aws cloudformation deploy \
		--profile ${AWS_CLI_SEC_PROFILE} \
		--template-file init-secrets.cf.yml \
		--stack-name ${SEC_SECRET_INIT_STACK_NAME} \
		--capabilities CAPABILITY_NAMED_IAM \
		--parameter-overrides \
			SecurityAccountId=${SECURITY_ACCOUNT_ID} \
			DevAccountId=${DEV_ACCOUNT_ID} \
			ProdAccountId=${PROD_ACCOUNT_ID}
	aws cloudformation update-termination-protection \
		--profile ${AWS_CLI_SEC_PROFILE} \
		--stack-name ${SEC_SECRET_INIT_STACK_NAME} \
		--enable-termination-protection

.PHONY: upload-flowable-non-prod-license
upload-flowable-non-prod-license:
	aws \
		--profile ${AWS_CLI_SEC_PROFILE} \
		secretsmanager put-secret-value \
		--secret-id flowable/non_prod/flowableLicense \
		--secret-string file://${FLOWABLE_DEV_LICENSE_FILE} 

.PHONY: upload-flowable-prod-license
upload-flowable-prod-license:
	aws \
		--profile ${AWS_CLI_SEC_PROFILE} \
		secretsmanager put-secret-value \
		--secret-id flowable/prod/flowableLicense \
		--secret-string file://${FLOWABLE_PROD_LICENSE_FILE} 

.PHONY: set-flowable-non-prod-repo-auth
set-flowable-non-prod-repo-auth:
	aws \
		--profile ${AWS_CLI_SEC_PROFILE} \
		secretsmanager put-secret-value \
		--secret-id flowable/non_prod/flowableRepoAuth \
		--secret-string '{"flowable_repo_username":"${FLOWABLE_REPO_AUTH_USERNAME}","flowable_repo_password":"${FLOWABLE_REPO_AUTH_PASSWORD}"}'

.PHONY: set-flowable-prod-repo-auth
set-flowable-prod-repo-auth:
	aws \
		--profile ${AWS_CLI_SEC_PROFILE} \
		secretsmanager put-secret-value \
		--secret-id flowable/prod/flowableRepoAuth \
		--secret-string '{"flowable_repo_username":"${FLOWABLE_REPO_AUTH_USERNAME}","flowable_repo_password":"${FLOWABLE_REPO_AUTH_PASSWORD}"}'

.PHONY: check-init-tf-backend-drift
check-init-tf-backend-drift:
	$(call show_cfn_drift,${TF_BACKEND_INIT_STACK_NAME})

import-terragrunt-changeset.json:
	@aws cloudformation create-change-set \
		--stack-name ${TF_BACKEND_INIT_STACK_NAME} \
		--change-set-name ${TF_BACKEND_INIT_STACK_NAME}-import-terragrunt \
		--change-set-type IMPORT \
		--template-body file://admin/init-admin-account.cf.yml \
		--capabilities CAPABILITY_NAMED_IAM \
		--parameters \
			ParameterKey=AdminAccountId,UsePreviousValue=True \
			ParameterKey=StateBucketName,UsePreviousValue=True \
			ParameterKey=StateLogBucketName,UsePreviousValue=True \
			ParameterKey=LockTableName,UsePreviousValue=True \
		--resources-to-import "[ \
			{ \
				\"ResourceType\":\"AWS::S3::Bucket\", \
				\"LogicalResourceId\":\"TerraformStateBucket\", \
				\"ResourceIdentifier\": { \
					\"BucketName\": \"${STATE_BUCKET_NAME}\" \
				} \
			}, \
			{ \
				\"ResourceType\":\"AWS::S3::Bucket\", \
				\"LogicalResourceId\":\"TerraformStateLogBucket\", \
				\"ResourceIdentifier\": { \
					\"BucketName\": \"${STATE_LOG_BUCKET_NAME}\" \
				} \
			}, \
			{ \
			\"ResourceType\":\"AWS::DynamoDB::Table\", \
				\"LogicalResourceId\":\"TerraformStateLockTable\", \
				\"ResourceIdentifier\": { \
					\"TableName\": \"${LOCK_TABLE_NAME}\" \
				} \
			} \
		]" | tee import-terragrunt-changeset.json

.PHONY: prepare-cfn-import-terragrunt
prepare-cfn-import-terragrunt: import-terragrunt-changeset.json
	$(eval CHANGE_SET_ID=$(shell jq -r .Id import-terragrunt-changeset.json))
	aws cloudformation wait change-set-create-complete \
		--change-set-name ${CHANGE_SET_ID} \
		--stack-name ${TF_BACKEND_INIT_STACK_NAME}
	@aws cloudformation describe-change-set \
		--change-set-name ${CHANGE_SET_ID} \
		--stack-name ${TF_BACKEND_INIT_STACK_NAME} \
		| jq '{ Changes, Status, StatusReason }'

.PHONY: discard-cfn-import-terragrunt
discard-cfn-import-terragrunt: import-terragrunt-changeset.json
	$(eval CHANGE_SET_ID=$(shell jq -r .Id import-terragrunt-changeset.json))
	aws cloudformation delete-change-set \
		--change-set-name ${CHANGE_SET_ID} \
		--stack-name ${TF_BACKEND_INIT_STACK_NAME}
	@rm import-terragrunt-changeset.json

.PHONY: cfn-import-terragrunt
cfn-import-terragrunt: import-terragrunt-changeset.json
	$(eval CHANGE_SET_ID=$(shell jq -r .Id import-terragrunt-changeset.json))
	aws cloudformation wait change-set-create-complete \
		--change-set-name ${CHANGE_SET_ID} \
		--stack-name ${TF_BACKEND_INIT_STACK_NAME}
	aws cloudformation execute-change-set \
		--change-set-name ${CHANGE_SET_ID} \
		--stack-name ${TF_BACKEND_INIT_STACK_NAME}
	@rm import-terragrunt-changeset.json
	aws cloudformation wait stack-import-complete \
		--stack-name ${TF_BACKEND_INIT_STACK_NAME}
	$(call show_cfn_drift,${TF_BACKEND_INIT_STACK_NAME})

.PHONY: test-tf-backend-assume
test-tf-backend-assume:
	aws sts assume-role \
		--role-arn ${TF_BACKEND_ROLE_ARN} \
		--role-session-name $(shell whoami)

.PHONY: init-all
init-all:
	for d in ${DEPLOYMENT_DIRS}; do \
		pushd $$d; \
		terragrunt init; \
		popd; \
	done

.PHONY: clean
clean:
	rm import-terragrunt-changeset.json
