#!/usr/bin/env bash
set -euo pipefail
# This script should be idempotent and retriable
# It's used to deploy a new region
# When adding a new dataplane aws account, this script should be
# invoked several times, each with a single region
remote_config=${CONFIG_PATH}
local_config=/tmp/base-config.yaml

bucket_name=${remote_config#s3://}
bucket_name=${bucket_name%%/*}
output_bucket_region=$(aws s3api get-bucket-location --bucket=$bucket_name --query="LocationConstraint" \
  --region=us-west-2 --output=text --no-cli-pager)
aws s3 cp "${remote_config}" "${local_config}" --region=$output_bucket_region

action=$(yq '.jobOptions.iam.action // "apply"' "${local_config}")
output_command="terraform output -json"
if [[ "${action}" == "apply" ]]; then
  action="apply -auto-approve"
elif [[ "${action}" == "plan" ]]; then
  action="plan -out=tfplan.binary"
  output_command="terraform show -json tfplan.binary | jq '(.planned_values.outputs // {} | with_entries(.value.value = if .value.value == null then \"known-after-apply\" else .value.value end) )'"
fi
cloud=$(yq '.cloudProvider' "${local_config}")
env=$(yq '.env' "${local_config}")
globalEnv=$(yq ".globalEnv // \"$env\"" "${local_config}")
region=$(yq '.region' "${local_config}")
logicalRegionName=$(yq '.name' "${local_config}")
cluster=$(yq '.k8s.name' "${local_config}")
eks_oidc=$(yq '.k8s.oidcIssuer' "${local_config}" | sed -E 's/^\s*.*:\/\///g')
controlplane_account=$(yq '.aws.controlplaneAccount' "${local_config}")
dataplane_accounts_json=$(yq -ojson '.aws.dataplaneAccounts' "${local_config}" | jq -c '.')
dataplane_accounts=$(yq -ojson '.aws.dataplaneAccounts' "${local_config}" | jq -r '.[]')
is_byoc=$(yq '.jobOptions.isByoc // "false"' "${local_config}")
job_id=$(yq '.jobId' "${local_config}")
remote_output=$(yq '.outputPath' "${local_config}")
local_output=/tmp/output.yaml
ROOT=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
tf_directory="${ROOT}/iam_tf"
tf_s3_bucket=$(yq '.terraformStateBucket' "${local_config}")
tf_s3_region=$(aws s3api get-bucket-location --bucket $tf_s3_bucket --region $region --query "LocationConstraint" --output text)
billing_sqs_arn=$(yq '.jobOptions.metering.billingSQSArn' "${local_config}")
resourceOwnerTag=$(yq '.jobOptions.resourceOwnerTag' "${local_config}")

# Provision cert-manager iam role in controlplane account
module_path="cert-manager/controlplane"
cd "${tf_directory}/${module_path}"
tf_state="${module_path}/${controlplane_account}-${env}-${logicalRegionName}-tfstate.json"
terraform init -backend-config="bucket=${tf_s3_bucket}" -backend-config="key=${tf_state}" -backend-config="region=${tf_s3_region}"
terraform ${action} -var="env=${env}" \
  -var="controlplane_account=${controlplane_account}" \
  -var="eks_oidc=${eks_oidc}" \
  -var="logical_region_name=${logicalRegionName}" \
  -var="auto_deploy_owner_tag=${resourceOwnerTag}"
cert_manager_role_arn=$(eval $output_command | jq '.role_arn.value')

# Provision external-secrets-operator iam role in controlplane account
module_path="external-secrets-operator/controlplane"
cd "${tf_directory}/${module_path}"
tf_state="${module_path}/${controlplane_account}-${env}-${logicalRegionName}-tfstate.json"
terraform init -backend-config="bucket=${tf_s3_bucket}" -backend-config="key=${tf_state}" -backend-config="region=${tf_s3_region}"
terraform ${action} -var="env=${env}" -var="secret_prefix=${globalEnv}" \
  -var="controlplane_account=${controlplane_account}" \
  -var="eks_oidc=${eks_oidc}" \
  -var="logical_region_name=${logicalRegionName}" \
  -var="auto_deploy_owner_tag=${resourceOwnerTag}"
external_secrets_operator_role_arn=$(eval $output_command | jq '.role_arn.value')

# Provision aws-lb-controller iam role in controlplane account
module_path="aws-load-balancer-controller/controlplane"
cd "${tf_directory}/${module_path}"
tf_state="${module_path}/${controlplane_account}-${env}-${logicalRegionName}-tfstate.json"
terraform init -backend-config="bucket=${tf_s3_bucket}" -backend-config="key=${tf_state}" -backend-config="region=${tf_s3_region}"
terraform ${action} -var="env=${env}" \
  -var="controlplane_account=${controlplane_account}" \
  -var="eks_oidc=${eks_oidc}" \
  -var="logical_region_name=${logicalRegionName}" \
  -var="auto_deploy_owner_tag=${resourceOwnerTag}"
aws_load_balancer_controller_role_arn=$(eval $output_command | jq '.role_arn.value')

# Provision cluster autoscaler iam role in controlplane account
module_path="cluster-autoscaler/controlplane"
cd "${tf_directory}/${module_path}"
tf_state="${module_path}/${controlplane_account}-${env}-${logicalRegionName}-tfstate.json"
terraform init -backend-config="bucket=${tf_s3_bucket}" -backend-config="key=${tf_state}" -backend-config="region=${tf_s3_region}"
terraform ${action} -var="env=${env}" \
  -var="controlplane_account=${controlplane_account}" \
  -var="eks_oidc=${eks_oidc}" \
  -var="logical_region_name=${logicalRegionName}" \
  -var="auto_deploy_owner_tag=${resourceOwnerTag}"
cluster_autoscaler_role_arn=$(eval $output_command | jq '.role_arn.value')

vector_role_arn=""
assume_o11y_role_arn=$(yq -ojson '.jobOptions.vector.o11yRoleArn' "${local_config}" | jq -r '.[]')
module_path="vector-agent/controlplane"
cd "${tf_directory}/${module_path}"
tf_state="${module_path}/${controlplane_account}-${env}-${logicalRegionName}-tfstate.json"
terraform init -backend-config="bucket=${tf_s3_bucket}" -backend-config="key=${tf_state}" -backend-config="region=${tf_s3_region}"
terraform ${action} -var="env=${env}" \
  -var="logical_region_name=${logicalRegionName}" \
  -var="controlplane_account=${controlplane_account}" \
  -var="assume_o11y_role_arn=${assume_o11y_role_arn}" \
  -var="eks_oidc=${eks_oidc}" \
  -var="auto_deploy_owner_tag=${resourceOwnerTag}"
vector_role_arn=$(eval $output_command | jq '.role_arn.value')

if $is_byoc; then
  byoc_dataplane_account=$(yq '.aws.dataplaneAccounts.0' "${local_config}")
  write_only_role_name=$(yq '.jobOptions.metering.writeOnlyRoleName // "tidbcloud-metering-write-only-role"' "${local_config}")
  read_write_role_name=$(yq '.jobOptions.metering.readWriteRoleName // "tidbcloud-metering-read-write-role"' "${local_config}")
  metering_write_only_role_arn="arn:aws:iam::${byoc_dataplane_account}:role/${write_only_role_name}"
  metering_read_write_role_arn="arn:aws:iam::${byoc_dataplane_account}:role/${read_write_role_name}"
else
  metering_read_write_role_arn="arn:aws:iam::${controlplane_account}:role/${env}-${logicalRegionName}-metering-read-write"
fi

# Provision dataplane-manager iam role in controlplane account
module_path="dataplane-manager/controlplane"
cd "${tf_directory}/${module_path}"
tf_state="${module_path}/${controlplane_account}-${env}-${logicalRegionName}-tfstate.json"
dataplane_manager_assumed_role_name=$(yq '.jobOptions.dataplaneManager.dataplaneAssumedRole // "tidbcloud-dataplane-manager-assumed-role"' "${local_config}")
terraform init -backend-config="bucket=${tf_s3_bucket}" -backend-config="key=${tf_state}" -backend-config="region=${tf_s3_region}"
terraform ${action} -var="env=${env}" \
  -var="controlplane_account=${controlplane_account}" \
  -var="dataplane_accounts=${dataplane_accounts_json}" \
  -var="eks_oidc=${eks_oidc}" \
  -var="logical_region_name=${logicalRegionName}" \
  -var="is_byoc=${is_byoc}" \
  -var="dataplane_role_name=${dataplane_manager_assumed_role_name}" \
  -var="metering_read_write_role_arn=${metering_read_write_role_arn}" \
  -var="billing_sqs_arn=${billing_sqs_arn}" \
  -var="auto_deploy_owner_tag=${resourceOwnerTag}"
dataplane_manager_role_arn=$(eval $output_command | jq -r '.role_arn.value')

if $is_byoc; then
  metering_bucket_name=""
else
  module_path="metering/premium"
  cd "${tf_directory}/${module_path}"
  tf_state="${module_path}/${controlplane_account}-${env}-${logicalRegionName}-tfstate.json"
  terraform init -backend-config="bucket=${tf_s3_bucket}" -backend-config="key=${tf_state}" -backend-config="region=${tf_s3_region}"
  terraform ${action} -var="env=${env}" \
    -var="region=${region}" \
    -var="logical_region_name=${logicalRegionName}" \
    -var="dataplane_manager_role_arn=${dataplane_manager_role_arn}" \
    -var="dataplane_accounts=${dataplane_accounts_json}" \
    -var="dataplane_manager_assumed_role_name=${dataplane_manager_assumed_role_name}" \
    -var="billing_sqs_arn=${billing_sqs_arn}" \
    -var="auto_deploy_owner_tag=${resourceOwnerTag}"
  metering_write_only_role_arn=$(eval $output_command | jq -r '.metering_write_only_role_arn.value')
  metering_read_write_role_arn_new=$(eval $output_command | jq -r '.metering_read_write_role_arn.value')
  metering_bucket_name=$(eval $output_command | jq '.metering_bucket_name.value')
  if [[ "$metering_read_write_role_arn" != "$metering_read_write_role_arn_new" ]]; then
    echo "Error: metering_read_write_role_arn changed from $metering_read_write_role_arn to $metering_read_write_role_arn_new"
    exit 1
  fi
fi


cat <<EOF > "${local_output}"
dataplane_manager:
  roleArn: ${dataplane_manager_role_arn}
certManager:
  roleArn: ${cert_manager_role_arn}
externalSecretsOperator:
  roleArn: ${external_secrets_operator_role_arn}
awsLoadBalancerController:
  roleArn: ${aws_load_balancer_controller_role_arn}
clusterAutoscaler:
  roleArn: ${cluster_autoscaler_role_arn}
vector:
  roleArn: ${vector_role_arn}
metering:
  bucketName: $metering_bucket_name
  writeOnlyRoleArn: $metering_write_only_role_arn
  readWriteRoleArn: $metering_read_write_role_arn
EOF
echo "Write output to S3..."
aws s3 cp "${local_output}" "${remote_output}" --region=$output_bucket_region
