#!/usr/bin/env bash

set -euo pipefail
# Usage: ./deploy-new-gcp-region.sh <region> <env> gcp <jsonFile> <logicalRegionName>
# Creates envs/gcp-${env}-${logicalRegionName}/
# When changing this script, remember to modify the corresponding github action
region=${1}
env=${2}
cloud=${3}
json_file_path=${4}
logicalRegionName=${5}

if [[ "${cloud}" != "gcp" ]]; then
  echo "cloud must be gcp, got: ${cloud}"
  exit 1
fi

additional_args=$(jq -r '.' "${json_file_path}")

echo "additional_args: ${additional_args}"

# additional_args is the unwrapped JSON object (workflow toJSON wraps it as a string).
args_json() {
  echo "${additional_args}" | jq -r "$1"
}

irsa_role_arn=$(args_json '.awsIrsaRoleArn')
assume_role_global_arn=$(args_json '.awsAssumeRoleGlobalArn')
availability_zones=$(args_json '.availabilityZones')
image_registry=$(args_json '.imageRegistry')

dataplane_accounts=$(args_json '.dataplaneAccounts')
auth0_audience=$(args_json '.auth0Audience')
auth0_domain=$(args_json '.auth0Domain')
global_controlplane_ips=$(args_json '.globalControlplaneIPs')
regional_controlplane_ips=$(args_json '.regionalControlplaneIPs')
o11y_regional_service_ips=$(args_json '.o11yRegionalServiceIPs')
clinic_ips=$(args_json '.clinicIPs')
bastion_ips=$(args_json '.bastionIPs')
authorized_subjects=$(args_json '.authorizedSubjects')
public_hosted_zone_domain=$(args_json '.publicHostedZoneDomain')
public_hosted_zone_id=$(args_json '.publicHostedZoneID')
o11y_regional_service_endpoint=$(args_json '.o11yRegionalServiceEndpoint')
pca_arn=$(args_json '.pcaArn')
acct2shared_buckets=$(args_json '.acct2sharedBuckets')

# GCP-specific args
gcp_drs_service_account=$(args_json '.gcpDrsServiceAccount')
controlplane_project=$(args_json '.controlplaneProject')
default_dataplane_project=$(args_json '.defaultDataplaneProject')
aws_region=$(args_json '.awsRegion // "us-west-2"')

ROOT=$(cd $(dirname ${BASH_SOURCE[0]}) && pwd)
deploy_dir="${ROOT}/envs/${cloud}-${env}-${logicalRegionName}"
variant_dir="${ROOT}/variants/${env}-${cloud}"

if [ ! -d "${variant_dir}" ]; then
  echo "Variant directory does not exist: ${variant_dir}"
  exit 1
fi

if [ -e ${deploy_dir} ]; then
  echo "New region deploy directory already exist"
  exit 1
fi

mkdir -p "${deploy_dir}"
echo "Prepare manifest files"
cp "${variant_dir}/kustomization_tmpl.yaml" "${deploy_dir}/kustomization.yaml"
cp "${variant_dir}/version_tmpl.yaml" "${deploy_dir}/version.yaml"
cp "${variant_dir}/service_account_tmpl.yaml" "${deploy_dir}/service_account.yaml"
cp "${variant_dir}/deployment_tmpl.yaml" "${deploy_dir}/deployment.yaml"

if [[ "${env}" == "dev" ]]; then
  cp "${variant_dir}/role.yaml" "${deploy_dir}/role.yaml"
fi

mkdir "${deploy_dir}/config"
echo "Prepare config files"
cp "${variant_dir}/config/k8s-addon-templates.yaml" "${deploy_dir}/config/k8s-addon-templates.yaml"
cp "${variant_dir}/config/k8s-dedicated-templates_tmpl.yaml" "${deploy_dir}/config/k8s-dedicated-templates.yaml"
cp "${variant_dir}/config/k8s-dp-templates_tmpl.yaml" "${deploy_dir}/config/k8s-dp-templates.yaml"
cp "${variant_dir}/config/k8s-infra-templates_tmpl.yaml" "${deploy_dir}/config/k8s-infra-templates.yaml"
cp "${variant_dir}/config/root-config_tmpl.yaml" "${deploy_dir}/config/root-config.yaml"

if [[ "$OSTYPE" == "darwin"* ]]; then
    # macOS
    SED_IN_PLACE=(-i '')
else
    # Linux and others
    SED_IN_PLACE=(-i)
fi

find "${deploy_dir}" -type f -exec sed "${SED_IN_PLACE[@]}" "s|TMPL_REGION|${region}|g" {} \;
sed "${SED_IN_PLACE[@]}" "s|TMPL_IRSA_ROLE_ARN|${irsa_role_arn}|g" "${deploy_dir}/deployment.yaml"
sed "${SED_IN_PLACE[@]}" "s|TMPL_AWS_REGION|${aws_region}|g" "${deploy_dir}/deployment.yaml"
sed "${SED_IN_PLACE[@]}" "s|TMPL_GCP_DRS_SERVICE_ACCOUNT|${gcp_drs_service_account}|g" "${deploy_dir}/service_account.yaml"
find "${deploy_dir}" -type f -exec sed "${SED_IN_PLACE[@]}" "s|IMAGE_REGISTRY|${image_registry}|g" {} \;
# replace the auth0 audience and domain
sed "${SED_IN_PLACE[@]}" "s|TMPL_AUTH0_AUDIENCE|${auth0_audience}|g" "${deploy_dir}/config/k8s-dedicated-templates.yaml"
sed "${SED_IN_PLACE[@]}" "s|TMPL_AUTH0_DOMAIN|${auth0_domain}|g" "${deploy_dir}/config/k8s-dedicated-templates.yaml"
# replace the public hosted zone domain and id
sed "${SED_IN_PLACE[@]}" "s|TMPL_PUBLIC_HOSTED_ZONE_DOMAIN|${public_hosted_zone_domain}|g" "${deploy_dir}/config/root-config.yaml"
sed "${SED_IN_PLACE[@]}" "s|TMPL_PUBLIC_HOSTED_ZONE_ID|${public_hosted_zone_id}|g" "${deploy_dir}/config/root-config.yaml"
# replace the o11y regional service endpoint
sed "${SED_IN_PLACE[@]}" "s|TMPL_O11Y_REGIONAL_SERVICE_ENDPOINT|${o11y_regional_service_endpoint}|g" "${deploy_dir}/config/root-config.yaml"
# replace the pca arn
sed "${SED_IN_PLACE[@]}" "s|TMPL_PCA_ARN|${pca_arn}|g" "${deploy_dir}/config/root-config.yaml"
# replace the controlplane project
sed "${SED_IN_PLACE[@]}" "s|TMPL_CONTROLPLANE_PROJECT|${controlplane_project}|g" "${deploy_dir}/config/root-config.yaml"

yq e -i ".regionConfig.zones |= $availability_zones" ${deploy_dir}/config/root-config.yaml

mkdir "${deploy_dir}/account"
echo "Prepare account-list.yaml"
# generate the account list, path: account/account-list.yaml
account_list=${deploy_dir}/account/account-list.yaml
cat <<EOF > ${account_list}
apiVersion: v1
kind: ConfigMap
metadata:
  name: account-list
  labels:
    cloud.pingcap.com/bizType: dedicated
data:
  default: "${default_dataplane_project}"
  list: |
EOF

for account in $(echo "${dataplane_accounts}" | jq -r '.[]'); do
  account_shared_buckets=($(echo "${acct2shared_buckets}" | jq -r --arg acct "${account}" '.[$acct][]'))

  cat <<EOF >> ${account_list}
    - gcpaccountinfo:
        projectID: ${account}
      sharedBucketBundle:
        defaultBucketName: ${account_shared_buckets[0]}
        buckets:
EOF
  for bucket in "${account_shared_buckets[@]}"; do
    echo "          - bucketName: ${bucket}" >> ${account_list}
  done
done

echo "Prepare providerconfig.yaml"
providerconfig_config=${deploy_dir}/account/providerconfig.yaml
cat <<EOF > ${providerconfig_config}
apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
  name: "provider-aws-gr"
spec:
  assumeRoleARN: ${assume_role_global_arn}
  credentials:
    source: InjectedIdentity
EOF

for account in $(echo "${dataplane_accounts}" | jq -r '.[]'); do
  cat <<EOF >> ${providerconfig_config}
---
apiVersion: gcp.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
  name: "${account}"
spec:
  projectID: ${account}
  credentials:
    source: InjectedIdentity
EOF
done

if [[ "${env}" == "staging" ]] && echo "${additional_args}" | jq -e '.projectBindings | type == "array" and length > 0' >/dev/null; then
  echo "Prepare binding.yaml"
  binding_file="${deploy_dir}/account/binding.yaml"
  first=true
  while IFS= read -r binding; do
    project_id=$(echo "${binding}" | jq -r '.projectId')
    default_project=$(echo "${binding}" | jq -r '.defaultProject')
    if [[ "${first}" == true ]]; then
      first=false
    else
      echo "---" >> "${binding_file}"
    fi
    cat <<EOF >> "${binding_file}"
apiVersion: v1
kind: ConfigMap
metadata:
  name: project-${project_id}
  labels:
    cloud.pingcap.com/bizType: dedicated
    tags.tidbcloud.com/environment: staging
    tags.tidbcloud.com/servicetype: dedicated
    tags.tidbcloud.com/usedby: dbaas-control-plane-shoot
data:
  default: "${default_project}"
EOF
  done < <(echo "${additional_args}" | jq -c '.projectBindings[]')
  yq e -i '.resources += ["account/binding.yaml"]' "${deploy_dir}/kustomization.yaml"
fi

echo "set whitelist ip"
yq e -i ".appBoxConfig.apiserverPublicAccessCidrs |= ${bastion_ips} + ${global_controlplane_ips} + ${regional_controlplane_ips} + ${o11y_regional_service_ips}" \
  ${deploy_dir}/config/root-config.yaml
yq e -i ".[0].clusterProxy.helmValues.service.loadBalancerSourceRanges |= ${global_controlplane_ips} + ${regional_controlplane_ips} + ${clinic_ips}" \
  ${deploy_dir}/config/k8s-dedicated-templates.yaml
yq e -i ".[0].clusterGateway.helmValues.proxy.loadBalancerSourceRanges |= ${global_controlplane_ips} + ${regional_controlplane_ips} + ${clinic_ips}" \
  ${deploy_dir}/config/k8s-dedicated-templates.yaml
yq e -i ".[0].dataflowAgent.helmValues.service.loadBalancerSourceRanges |= ${global_controlplane_ips} + ${regional_controlplane_ips}" \
  ${deploy_dir}/config/k8s-dp-templates.yaml

echo "set authorized subjects"
yq e -i ".appBoxConfig.authorizedSubjects |= ${authorized_subjects}" ${deploy_dir}/config/root-config.yaml
