module "cloud-addon" {
  source = "../../../modules/app"
  depends_on = [
    module.o11y-infra-cd,
    azurerm_application_gateway.o11y,
    azurerm_federated_identity_credential.o11y,
  ]

  workflow = "new-region-cloud-addon.yaml"
  gh_repo  = "tidbcloud/observability"
  gh_ref   = local.o11y_workflow_ref
  parameters = merge(local.metadata_parameters, {
    args = jsonencode({
      hostedZoneName                      = local.hosted_zone_name
      privateLinkServiceName              = local.private_link_service_name
      privateLinkServiceResourceGroup     = local.resource_group
      subnetName                          = azurerm_subnet.private_endpoint.name
      imageRegistry                       = var.image_registry
      rsWAFID                             = azurerm_web_application_firewall_policy.rs.id
      dsWAFID                             = azurerm_web_application_firewall_policy.ds.id
      agicApplicationGatewayID            = azurerm_application_gateway.o11y.id
      agicApplicationGatewayName          = azurerm_application_gateway.o11y.name
      agicApplicationGatewayResourceGroup = azurerm_application_gateway.o11y.resource_group_name
      agicSubscriptionID                  = var.customer_subscription_id
      agicIdentityClientID                = local.identity_client_ids.agic
      byoc                                = true
    })
  })
  wait_workflow_success = true
  finalizer = {
    workflow = "destroy-region-cloud-addon.yaml"
    parameters = {
      vendor            = "azure"
      region            = var.cloud_region
      logicalRegionName = var.logical_region_name
      env               = var.env
    }
  }
}

resource "null_resource" "cloud_addon_svc_finalizer" {
  depends_on = [
    module.cloud-addon,
    module.aks,
  ]

  lifecycle {
    ignore_changes = all
  }

  triggers = {
    kubeconfig_path = module.kubeconfig.path
  }

  provisioner "local-exec" {
    when        = destroy
    interpreter = ["bash", "-c"]
    environment = {
      KUBECONFIG = self.triggers.kubeconfig_path
    }
    command = <<-EOT
      set -xeuo pipefail

      kubectl delete svc nginx-write -n kube-system --ignore-not-found
      kubectl delete svc ingress-nginx-write-controller -n kube-system --ignore-not-found
      kubectl delete svc ingress-nginx-write-controller-internal -n kube-system --ignore-not-found
      kubectl delete ingress nginx-read -n kube-system --ignore-not-found
      kubectl delete ingress nginx-read -n observability --ignore-not-found
      kubectl delete ingress nginx-ingress -n kube-system --ignore-not-found
      kubectl delete ingress nginx-ingress -n observability --ignore-not-found
      kubectl delete ingress regionalingress -n observability --ignore-not-found

      kubectl wait --for=delete svc/nginx-write -n kube-system --timeout=600s
      kubectl wait --for=delete svc/ingress-nginx-write-controller -n kube-system --timeout=600s
      kubectl wait --for=delete svc/ingress-nginx-write-controller-internal -n kube-system --timeout=600s
      kubectl wait --for=delete ingress/nginx-read -n kube-system --timeout=600s
      kubectl wait --for=delete ingress/nginx-read -n observability --timeout=600s
      kubectl wait --for=delete ingress/nginx-ingress -n kube-system --timeout=600s
      kubectl wait --for=delete ingress/nginx-ingress -n observability --timeout=600s
      kubectl wait --for=delete ingress/regionalingress -n observability --timeout=600s
    EOT
  }
}

module "cloud-addon-cd" {
  depends_on = [module.cloud-addon]
  source     = "../../../modules/app"

  kubeconfig_path = module.kubeconfig.path
  workflow        = "cloud-addon-cd.yaml"
  gh_repo         = "tidbcloud/observability"
  gh_ref          = local.o11y_workflow_ref
  parameters      = local.cd_parameters
  services = [
    {
      name      = "deploy/ingress-nginx-read-controller"
      namespace = "observability"
      wait_for  = "jsonpath='{.status.availableReplicas}'=REPLICAS"
    },
    {
      name      = "deploy/ingress-nginx-write-controller"
      namespace = "kube-system"
      wait_for  = "jsonpath='{.status.availableReplicas}'=REPLICAS"
    },
    {
      name      = "deploy/ingress-azure"
      namespace = "kube-system"
      wait_for  = "jsonpath='{.status.availableReplicas}'=REPLICAS"
    }
  ]
  wait_workflow_success = true
  check_before_destroy  = false
}

resource "null_resource" "wait_nginx_write_pls" {
  depends_on = [module.cloud-addon-cd]

  triggers = {
    private_link_service_name = local.private_link_service_name
    resource_group_name       = local.resource_group
    kubeconfig_path           = module.kubeconfig.path
  }

  provisioner "local-exec" {
    interpreter = ["bash", "-c"]
    environment = {
      KUBECONFIG = self.triggers.kubeconfig_path
    }
    command = <<-EOT
      set -euo pipefail

      start_time=$(date +%s)
      timeout=600
      interval=10

      while [ $(($(date +%s) - start_time)) -lt $timeout ]; do
        ip="$(kubectl get svc ingress-nginx-write-controller-internal -n kube-system -ojsonpath='{.status.loadBalancer.ingress[*].ip}' 2>/dev/null || true)"
        if [ -n "$ip" ] && az network private-link-service show --name "${self.triggers.private_link_service_name}" --resource-group "${self.triggers.resource_group_name}" >/dev/null 2>&1; then
          az network private-link-service update \
            --name "${self.triggers.private_link_service_name}" \
            --resource-group "${self.triggers.resource_group_name}" \
            --tags "tidbcloud-auto-deploy-owner=${local.o11y_name}"
          exit 0
        fi

        sleep "$interval"
      done

      echo "Timed out waiting for ingress-nginx-write-controller-internal and Azure Private Link Service ${self.triggers.private_link_service_name}" >&2
      exit 1
    EOT
  }
}

data "external" "private_link_service" {
  depends_on = [null_resource.wait_nginx_write_pls]

  program = ["bash", "-lc", <<-EOT
      set -euo pipefail
      err_file="$(mktemp)"
      trap 'rm -f "$err_file"' EXIT

      if id="$(az network private-link-service show \
        --name '${local.private_link_service_name}' \
        --resource-group '${local.resource_group}' \
        --query id -o tsv 2>"$err_file")"; then
        jq -n --arg id "$id" '{"id":$id}'
      elif grep -q "ResourceNotFound" "$err_file"; then
        jq -n --arg id "" '{"id":$id}'
      else
        cat "$err_file" >&2
        exit 1
      fi
  EOT
  ]
}
