#!/bin/bash

set -e

vendor=${1}
env=${2}
# logical region name
region=${3}
logical_region=${4}
cluster=${5}
json_file_path=${6}
args=$(jq -r '.' "${json_file_path}")
rs_address=$(echo $args | jq -r '.rsAddress')
ds_address=$(echo $args | jq -r '.dsAddress')
tenant_id=$(echo $args | jq -r '.tenantID')
access_principal=$(echo $args | jq -r '.accessPrincipal')
access_external_id=$(echo $args | jq -r '.accessExternalID')

# throw error if any of the arguments are not set
if [ -z "$vendor" ] || [ -z "$env" ] || [ -z "$region" ] || [ -z "$logical_region" ] || [ -z "$cluster" ]; then
  echo "Error: Missing required arguments."
  echo "Usage: $0 <vendor> <env> <region> <logical_region> <cluster> [args]"
  echo ""
  echo "Parameters:"
  echo "  vendor         - Cloud vendor (aws, gcp, azure, alicloud)"
  echo "  env            - Environment (dev, staging, prod)"
  echo "  region         - Physical region name"
  echo "  logical_region - Logical region name"
  echo "  cluster        - Cluster name"
  echo ""
  echo "Route behavior:"
  echo "  - If tenant_id is provided: Creates 'byoc:<tenant_id>:.*' -> logical_region route"
  echo "  - If tenant_id is empty and region is primary: Creates '.*' -> logical_region route"
  exit 1
fi
echo "region: $region env: $env vendor: $vendor logical_region: $logical_region cluster: $cluster"

ROOT=$(cd $(dirname ${BASH_SOURCE[0]}) && pwd)
GLOBAL_KONG_PROXY="kong-kong-proxy.kong.svc.cluster.local"

dedupe_region_entries() {
  local file_path="$1"
  local vendor_name="$2"
  local physical_region="$3"

  local merged_routers
  merged_routers=$(jq -c \
    --arg vendor "$vendor_name" \
    --arg region "$physical_region" '
      .vendors[$vendor]
      | [ .[] | select(.region == $region) | .routers[] ]
      | group_by([.dnsAddress, .logicalRegionName, (.accessPrincipal // ""), (.accessExternalID // "")])
      | map(
          . as $group
          | ($group[0]
            | if ([ $group[] | (.primary // false) ] | any) then . + {"primary": true} else del(.primary) end)
        )
    ' "$file_path")

  jq \
    --arg vendor "$vendor_name" \
    --arg region "$physical_region" \
    --argjson mergedRouters "$merged_routers" '
      .vendors[$vendor] |= (
        reduce .[] as $item (
          {"seen": false, "regions": []};
          if $item.region != $region then
            .regions += [$item]
          elif .seen then
            .
          else
            .seen = true
            | .regions += [{
                "region": $region,
                "routers": $mergedRouters
              }]
          end
        ) | .regions
      )
    ' "$file_path" > "$file_path.tmp" && mv "$file_path.tmp" "$file_path"
}

echo "register logical region to globalserver configmap"
global_file_path="$ROOT/manifests/${env}/meta.json"
global_configmap_path="$ROOT/manifests/${env}/configmap.yaml"

if [ "$env" == "dev" ]; then
  default_dns_zone="observability-dev.pingcap.cloud"
elif [ "$env" == "staging" ]; then
  default_dns_zone="observability-staging.pingcap.cloud"
else
  default_dns_zone="observability.tidbcloud.com"
fi

if [ -z "$rs_address" ]; then
  rs_address="https://www.rs.${logical_region}.${vendor}.${default_dns_zone}"
fi
if [ -z "$ds_address" ]; then
  ds_address="https://www.ds.${logical_region}.${vendor}.${default_dns_zone}"
fi

if [[ ! "$rs_address" =~ ^https:// ]] && [[ ! "$rs_address" =~ ^http:// ]]; then
  rs_address="https://$rs_address"
fi
if [[ ! "$ds_address" =~ ^https:// ]] && [[ ! "$ds_address" =~ ^http:// ]]; then
  ds_address="https://$ds_address"
fi

# update globalserver configmap json
# Construct router object
ROUTER_JSON=$(jq -n \
                  --arg dns "$rs_address" \
                  --arg dp "$ds_address" \
                  --arg lr "$logical_region" \
                  '{dnsAddress: $dns, dataplaneAddress: $dp, logicalRegionName: $lr}')

if [ "$access_principal" != "null" ] && [ -n "$access_principal" ]; then
  ROUTER_JSON=$(echo "$ROUTER_JSON" | jq --arg ap "$access_principal" '. + {accessPrincipal: $ap}')
fi

if [ "$access_external_id" != "null" ] && [ -n "$access_external_id" ]; then
  ROUTER_JSON=$(echo "$ROUTER_JSON" | jq --arg ae "$access_external_id" '. + {accessExternalID: $ae}')
fi

if ! jq -e ".vendors.${vendor} | any(.region == \"${region}\")" $global_file_path > /dev/null; then
  # If region doesn't exist, add as primary region
  echo "Adding new logical region '${logical_region}' as primary"
  jq --argjson router "$ROUTER_JSON" ".vendors.${vendor}+=[{\"region\":\"${region}\",\"routers\":[\$router + {\"primary\":true}]}]" $global_file_path > $global_file_path.tmp && mv $global_file_path.tmp $global_file_path

  # Add routes for the new region
  route_key="${vendor}-${region}"
  echo "Adding routes for route key '${route_key}'"

  # Initialize the route key if it doesn't exist
  if ! jq -e ".routes.\"${route_key}\"" $global_file_path > /dev/null; then
    jq ".routes.\"${route_key}\" = {}" $global_file_path > $global_file_path.tmp && mv $global_file_path.tmp $global_file_path
  fi

  # Add tenant-specific route if tenant_id is provided
  if [ "$tenant_id" != "null" ] && [ -n "$tenant_id" ]; then
    tenant_route="byoc:${tenant_id}:.*"
    echo "Adding tenant-specific route: ${tenant_route} -> ${logical_region}"
    jq ".routes.\"${route_key}\".\"${tenant_route}\" = \"${logical_region}\"" $global_file_path > $global_file_path.tmp && mv $global_file_path.tmp $global_file_path
  else
    default_route=".*"
    echo "Adding default route: ${default_route} -> ${logical_region}"
    jq ".routes.\"${route_key}\".\"${default_route}\" = \"${logical_region}\"" $global_file_path > $global_file_path.tmp && mv $global_file_path.tmp $global_file_path
  fi


else
  # If region exists, check if this router already exists
  if ! jq -e ".vendors.${vendor}[] | select(.region == \"${region}\") | .routers[] | select(.dnsAddress == \"${rs_address}\")" $global_file_path > /dev/null; then
    echo "Appending router to existing logical region '${logical_region}'"
    jq --argjson router "$ROUTER_JSON" ".vendors.${vendor}[] |= if .region == \"${region}\" then .routers += [\$router] else . end" $global_file_path > $global_file_path.tmp && mv $global_file_path.tmp $global_file_path
  else
    echo "Router with address '${rs_address}' already exists for logical region '${logical_region}'"
  fi

  # Add tenant-specific route if tenant_id is provided
  if [ "$tenant_id" != "null" ] && [ -n "$tenant_id" ]; then
    route_key="${vendor}-${region}"
    tenant_route="byoc:${tenant_id}:.*"
    echo "Adding tenant-specific route: ${tenant_route} -> ${logical_region}"
    jq ".routes.\"${route_key}\".\"${tenant_route}\" = \"${logical_region}\"" $global_file_path > $global_file_path.tmp && mv $global_file_path.tmp $global_file_path
  fi
fi

echo "dedupe duplicated region entries and router metadata for '${vendor}-${region}'"
dedupe_region_entries "$global_file_path" "$vendor" "$region"

if [[ $env != "staging" ]]; then
  echo "register logical region to karma configMap.rawConfig.alertmanager.servers if not exist"
  KARMA_VALUES_PATH="$ROOT/karma/values-${env}.yaml"
  AM_SERVER_NAME="${vendor}-${logical_region}"
  #https://www.ds.us-west-2.aws.observability-dev.pingcap.cloud/internal/alerts/
  AM_SERVER_URI="${ds_address}/internal/alerts/"
  AM_SELF_MONITORING_SERVER_NAME="o11y-selfmon-${vendor}-${logical_region}"
  #https://www.ds.us-west-2.aws.observability-dev.pingcap.cloud/internal/alerts/self-monitoring/
  AM_SELF_MONITORING_SERVER_URI="${ds_address}/internal/alerts/self-monitoring/"

  HEADERS_JSON="{}"
  if [ "$tenant_id" != "null" ] && [ -n "$tenant_id" ]; then
    AM_SERVER_URI="http://${GLOBAL_KONG_PROXY}/internal/internal/alerts/"
    AM_SELF_MONITORING_SERVER_URI="http://${GLOBAL_KONG_PROXY}/internal/internal/alerts/self-monitoring/"
    HEADERS_JSON="{\"X-Region-Id\":\"${vendor}-${region}\",\"X-Biz-Type\":\"byoc\",\"X-Org-Id\":\"${tenant_id}\"}"
  fi

  # check if the AM_SERVER_NAME is already in the configMap.rawConfig.alertmanager.servers
  if ! yq -e ".configMap.rawConfig.alertmanager.servers[] | select(.name == \"${AM_SERVER_NAME}\")" $KARMA_VALUES_PATH > /dev/null 2>&1; then
    if [ "$tenant_id" != "null" ] && [ -n "$tenant_id" ]; then
      yq -i ".configMap.rawConfig.alertmanager.servers += [{\"name\":\"${AM_SERVER_NAME}\",\"uri\":\"${AM_SERVER_URI}\",\"proxy\":true,\"headers\":$HEADERS_JSON}]" $KARMA_VALUES_PATH
    else
      yq -i ".configMap.rawConfig.alertmanager.servers += [{\"name\":\"${AM_SERVER_NAME}\",\"uri\":\"${AM_SERVER_URI}\",\"proxy\":true}]" $KARMA_VALUES_PATH
    fi
  fi

  if ! yq -e ".configMap.rawConfig.alertmanager.servers[] | select(.name == \"${AM_SELF_MONITORING_SERVER_NAME}\")" $KARMA_VALUES_PATH > /dev/null 2>&1; then
    if [ "$tenant_id" != "null" ] && [ -n "$tenant_id" ]; then
      yq -i ".configMap.rawConfig.alertmanager.servers += [{\"name\":\"${AM_SELF_MONITORING_SERVER_NAME}\",\"uri\":\"${AM_SELF_MONITORING_SERVER_URI}\",\"proxy\":true,\"headers\":$HEADERS_JSON}]" $KARMA_VALUES_PATH
    else
      yq -i ".configMap.rawConfig.alertmanager.servers += [{\"name\":\"${AM_SELF_MONITORING_SERVER_NAME}\",\"uri\":\"${AM_SELF_MONITORING_SERVER_URI}\",\"proxy\":true}]" $KARMA_VALUES_PATH
    fi
  fi
fi

echo "register logical region to grafana datasources"
PROME_STACK_PATH="$ROOT/../infra-v2/kube-prometheus-stack/envs/${env}/global-aws-us-west-2.yaml"
PROM_DATASOURCE_NAME="Prometheus-regional-${logical_region}"
PROM_DATASOURCE_URI="${ds_address}/prom/self-monitoring"
LOKI_DATASOURCE_NAME="Loki-regional-${logical_region}"
LOKI_DATASOURCE_URI="${ds_address}/loki/self-monitoring"

if [[ $vendor == "alicloud" ]]; then
  PROM_DATASOURCE_NAME="Prometheus-regional-alicloud-${logical_region}"
  LOKI_DATASOURCE_NAME="Loki-regional-alicloud-${logical_region}"
fi

# - name: Prometheus-regional-us-west-2
#   access: proxy
#   jsonData:
#     httpMethod: POST
#     timeInterval: 30s
#   orgId: 1
#   type: prometheus
#   url: https://www.ds.us-west-2.aws.observability-dev.pingcap.cloud/prom/self-monitoring
if ! yq -e ".grafana.additionalDataSources[] | select(.name == \"${PROM_DATASOURCE_NAME}\")" $PROME_STACK_PATH > /dev/null 2>&1; then
  if [ "$tenant_id" != "null" ] && [ -n "$tenant_id" ]; then
    PROM_DATASOURCE_URI="http://${GLOBAL_KONG_PROXY}/internal/prom/self-monitoring"
    yq -i ".grafana.additionalDataSources += [{\"name\":\"${PROM_DATASOURCE_NAME}\",\"access\":\"proxy\",\"jsonData\":{\"httpMethod\":\"POST\",\"timeInterval\":\"30s\",\"httpHeaderName1\":\"X-Region-Id\",\"httpHeaderName2\":\"X-Biz-Type\",\"httpHeaderName3\":\"X-Org-Id\"},\"secureJsonData\":{\"httpHeaderValue1\":\"${vendor}-${region}\",\"httpHeaderValue2\":\"byoc\",\"httpHeaderValue3\":\"${tenant_id}\"},\"orgId\":1,\"type\":\"prometheus\",\"url\":\"${PROM_DATASOURCE_URI}\"}]" $PROME_STACK_PATH
  else
    yq -i ".grafana.additionalDataSources += [{\"name\":\"${PROM_DATASOURCE_NAME}\",\"access\":\"proxy\",\"jsonData\":{\"httpMethod\":\"POST\",\"timeInterval\":\"30s\"},\"orgId\":1,\"type\":\"prometheus\",\"url\":\"${PROM_DATASOURCE_URI}\"}]" $PROME_STACK_PATH
  fi
fi

# - name: Loki-regional-us-west-2
#   access: proxy
#   orgId: 1
#   type: loki
#   url: https://www.ds.us-west-2.aws.observability-dev.pingcap.cloud/loki/self-monitoring
if ! yq -e ".grafana.additionalDataSources[] | select(.name == \"${LOKI_DATASOURCE_NAME}\")" $PROME_STACK_PATH > /dev/null 2>&1; then
  if [ "$tenant_id" != "null" ] && [ -n "$tenant_id" ]; then
    LOKI_DATASOURCE_URI="http://${GLOBAL_KONG_PROXY}/internal/loki/self-monitoring"
    yq -i ".grafana.additionalDataSources += [{\"name\":\"${LOKI_DATASOURCE_NAME}\",\"access\":\"proxy\",\"jsonData\":{\"httpHeaderName1\":\"X-Region-Id\",\"httpHeaderName2\":\"X-Biz-Type\",\"httpHeaderName3\":\"X-Org-Id\"},\"secureJsonData\":{\"httpHeaderValue1\":\"${vendor}-${region}\",\"httpHeaderValue2\":\"byoc\",\"httpHeaderValue3\":\"${tenant_id}\"},\"orgId\":1,\"type\":\"loki\",\"url\":\"${LOKI_DATASOURCE_URI}\"}]" $PROME_STACK_PATH
  else
    yq -i ".grafana.additionalDataSources += [{\"name\":\"${LOKI_DATASOURCE_NAME}\",\"access\":\"proxy\",\"orgId\":1,\"type\":\"loki\",\"url\":\"${LOKI_DATASOURCE_URI}\"}]" $PROME_STACK_PATH
  fi
fi

if [[ $env == "prod" ]]; then
  echo "register logical region to promxy config"
  PROMXY_VALUES_PATH="$ROOT/promxy/values-${env}.yaml"
  PROMXY_TARGET="${ds_address#https://}"
  PROMXY_SCHEME="https"
  PROMXY_PATH_PREFIX="/prom/self-monitoring/"
  IGNORE_ERROR_VALUE="false"
  HEADER_CONFIG=""

  if [ "$tenant_id" != "null" ] && [ -n "$tenant_id" ]; then
    PROMXY_TARGET="${GLOBAL_KONG_PROXY}"
    PROMXY_SCHEME="http"
    PROMXY_PATH_PREFIX="/internal/prom/self-monitoring/"
    IGNORE_ERROR_VALUE="true"
    HEADER_CONFIG="  headers:
    X-Region-Id: ${vendor}-${region}
    X-Biz-Type: byoc
    X-Org-Id: ${tenant_id}"
  fi

  # Check if the logical region already exists in promxy config
  # Note: We only check k8s_cluster label, not target, because BYOC regions share the same Kong proxy
  # but have different path_prefix and headers for routing
  if ! yq -e ".config.promxy.server_groups[] | select(.labels.k8s_cluster == \"${vendor}-${logical_region}\")" $PROMXY_VALUES_PATH > /dev/null 2>&1; then
    echo "Adding new server group for ${logical_region} to promxy config"

    cat > /tmp/new_server_group.yaml <<EOF
static_configs:
  - targets:
    - "${PROMXY_TARGET}"
labels:
  k8s_cluster: ${vendor}-${logical_region}
  provider: ${vendor}
anti_affinity: 10s
path_prefix: ${PROMXY_PATH_PREFIX}
scheme: ${PROMXY_SCHEME}
http_client:
  dial_timeout: 2s
  tls_config:
    insecure_skip_verify: true
${HEADER_CONFIG}
ignore_error: ${IGNORE_ERROR_VALUE}
EOF

    # Add the new server group to the existing server_groups array
    yq -i '.config.promxy.server_groups += [load("/tmp/new_server_group.yaml")]' $PROMXY_VALUES_PATH
    rm -f /tmp/new_server_group.yaml
  else
    echo "Logical region '${vendor}-${logical_region}' already exists in promxy config"
  fi
fi

echo "Region registration completed successfully!"
echo ""
echo "Routes added:"
route_key="${vendor}-${region}"
if [ "$tenant_id" != "null" ] && [ -n "$tenant_id" ]; then
  echo "  - Route key: ${route_key}"
  echo "  - Pattern: byoc:${tenant_id}:.* -> ${logical_region}"
else
  echo "  - Route key: ${route_key}"
  echo "  - Pattern: .* -> ${logical_region} (default route for primary region)"
fi
echo ""
echo "Updated files:"
echo "  - $global_file_path"
echo "  - $global_configmap_path"
if [[ $env != "staging" ]]; then
  echo "  - $KARMA_VALUES_PATH"
fi
echo "  - $PROME_STACK_PATH"
echo "  - $PROMXY_VALUES_PATH"
