data "terraform_remote_state" "seed" {
  backend = "s3"

  config = {
    bucket       = "autonomous-deployment-terraform-state"
    region       = "us-west-2"
    use_lockfile = true
    key          = "azure/account/seed/${var.env}.json"
  }
}

locals {
  shared_states = {
    base   = "aws/base/${var.env}.json"
    clinic = var.env == "dev" ? "aws/clinic/staging.json" : "aws/clinic/${var.env}.json"
    devops = var.env == "dev" ? "aws/devops/staging.json" : "aws/devops/${var.env}.json"
    argocd = "gke/argocd/${var.env}.json"
    o11y   = "aws/o11y-global/prod.json"
    runner = "gke/runner/prod.json"
  }
}

data "aws_s3_object" "shared_states" {
  for_each = local.shared_states

  bucket = "autonomous-deployment-terraform-state"
  key    = each.value

  provider = aws.tf_state
}

# V1 deliberately reuses the shared Azure regional MySQL, Key Vault, and
# metering backing resources from the existing azure/region state instead of
# creating a per-customer copy inside the BYOC seed stack.
data "aws_s3_object" "region_state" {
  bucket = "autonomous-deployment-terraform-state"
  key    = "azure/region/${var.env}-${var.cloud_region}.json"

  provider = aws.tf_state
}

locals {
  o11y_dns_zone_requested_name                = trimsuffix(trimspace(var.onboarding.o11y_dns_domain), ".")
  o11y_dns_zone_requested_resource_group_name = trimspace(var.onboarding.o11y_dns_resource_group)
  seed_outputs                                = data.terraform_remote_state.seed.outputs
  logical_region_name                         = var.logical_region_name != "" ? var.logical_region_name : "${var.cloud_region}-byoc-${var.customer_id}"
  cluster_name                                = "${var.env}-seed-${local.logical_region_name}"
  rcp_resource_group                          = "${var.env}-byoc-${var.customer_id}-${var.cloud_region}"
  rcp_vnet_cidr                               = "10.80.0.0/20"
  rcp_pe_subnet_cidr                          = "10.80.1.0/24"
  apiserver_zone_name                         = "private.${var.cloud_region}.azmk8s.io"
  gateway_zone_name                           = "privatelink.${var.customer_id}.${var.cloud_region}.gateway.${var.env}.azure.tidbcloud.com"
  base_account                                = local.seed_outputs.base_account
  controlplane_tenant_id                      = local.seed_outputs.controlplane_tenant_id
  controlplane_subscription                   = local.seed_outputs.controlplane_subscription_id
  controlplane_client_id                      = local.seed_outputs.controlplane_client_id
  image_registry                              = local.seed_outputs.image_registry
  effective_acr_id_scope                      = local.seed_outputs.acr_id_scope
  control_plane_admin_group_object_ids        = local.seed_outputs.admin_group_object_ids
  shared_state_outputs                        = { for key, state in data.aws_s3_object.shared_states : key => jsondecode(state.body).outputs }
  region_outputs                              = jsondecode(data.aws_s3_object.region_state.body).outputs
  base_outputs                                = local.shared_state_outputs["base"]
  clinic_outputs                              = local.shared_state_outputs["clinic"]
  devops_outputs                              = local.shared_state_outputs["devops"]
  argocd_outputs                              = local.shared_state_outputs["argocd"]
  o11y_outputs                                = local.shared_state_outputs["o11y"]
  runner_outputs                              = local.shared_state_outputs["runner"]
  controlplane_domain                         = var.controlplane_domain_name != "" ? var.controlplane_domain_name : "${var.env}.azure.tidbcloud.com"
  dataplane_domain_name                       = "${var.env}.azure.tidb-cloud.com"
  issuer_dns_zone                             = local.controlplane_domain
  public_hosted_zone                          = local.dataplane_domain_name
  regional_api_host                           = "${local.logical_region_name}.regional-api"
  service_address                             = var.service_address != "" ? var.service_address : "https://${local.regional_api_host}.${local.controlplane_domain}"
  global_controlplane_ips                     = formatlist("%s/32", local.base_outputs.public_ips.value)
  clinic_ips                                  = formatlist("%s/32", local.clinic_outputs.public_ips.value)
  bastion_ips                                 = formatlist("%s/32", local.devops_outputs.public_ips.value)
  auth0_audience                              = "${var.env}-proxy-service"
  auth0_domain                                = var.env == "prod" ? "tidb.auth0.com" : "tidb-${var.env}.us.auth0.com"
  customer_acr_resource_group                 = try(split("/", var.onboarding.customer_acr_resource_id)[4], "")
  controlplane_dns_zone_rg                    = var.controlplane_dns_zone_resource_group != "" ? var.controlplane_dns_zone_resource_group : data.external.controlplane_dns_zone.result.resource_group_name
  issuer_hosted_zone_resource_group           = local.controlplane_dns_zone_rg
  hosted_zone_resource_group                  = data.external.dataplane_dns_zone.result.resource_group_name
  jump_server_tenant_id                       = var.jump_server_tenant_id != "" ? var.jump_server_tenant_id : local.controlplane_tenant_id
  jump_server_subscription                    = var.jump_server_subscription_id != "" ? var.jump_server_subscription_id : local.controlplane_subscription
  jump_server_env                             = var.jump_server_env != "" ? var.jump_server_env : var.env
  o11y_aks_resource_group                     = trimspace(var.onboarding.o11y_aks_resource_group)
  o11y_cluster_name                           = local.o11y_aks_resource_group
  o11y_storage_resource_group                 = trimspace(var.onboarding.o11y_storage_resource_group)
  o11y_dns_zone_name                          = trimsuffix(data.azurerm_dns_zone.o11y.name, ".")
  o11y_dns_zone_resource_group_name           = data.azurerm_dns_zone.o11y.resource_group_name
  o11y_dns_zone_resource_id                   = data.azurerm_dns_zone.o11y.id
  o11y_image_registry                         = var.onboarding.customer_acr_login_server
  o11y_byoc_tenant_id                         = var.byoc_tenant_id
  o11y_identity_resource_group                = trimspace(var.onboarding.o11y_identity_resource_group)
  o11y_identity_names = {
    regional_server = trimspace(var.onboarding.o11y_regional_server_identity_name)
    vmbackup        = trimspace(var.onboarding.o11y_vmbackup_identity_name)
    loki            = trimspace(var.onboarding.o11y_loki_identity_name)
    velero          = trimspace(var.onboarding.o11y_velero_identity_name)
    agic            = trimspace(var.onboarding.o11y_agic_identity_name)
  }
  o11y_aks_identity_names = {
    control_plane = trimspace(var.onboarding.o11y_aks_control_plane_identity_name)
    kubelet       = trimspace(var.onboarding.o11y_aks_kubelet_identity_name)
  }
  required_o11y_identity_names = {
    regional_server = local.o11y_identity_names.regional_server
    vmbackup        = local.o11y_identity_names.vmbackup
    loki            = local.o11y_identity_names.loki
    velero          = local.o11y_identity_names.velero
    agic            = local.o11y_identity_names.agic
  }
  dataplane_accounts_contract_shape = [
    {
      subscriptionID      = var.onboarding.customer_subscription_id
      tenantID            = var.onboarding.customer_tenant_id
      clientID            = var.onboarding.multi_tenant_app_client_id
      bucketResourceGroup = var.onboarding.storage_accounts_resource_group
      customerACR = {
        resourceID  = var.onboarding.customer_acr_resource_id
        loginServer = var.onboarding.customer_acr_login_server
      }
    }
  ]
}

data "azurerm_dns_zone" "o11y" {
  provider = azurerm.customer_o11y_deployment

  name                = local.o11y_dns_zone_requested_name
  resource_group_name = local.o11y_dns_zone_requested_resource_group_name
}

check "onboarding_o11y_deployment_principal" {
  assert {
    condition     = var.onboarding.o11y_deployment_multi_tenant_app_client_id != ""
    error_message = "customerOnboarding.o11y_deployment_multi_tenant_app_client_id must be set to the temporary O11Y deployment multi-tenant app client ID."
  }

  assert {
    condition     = lower(var.onboarding.o11y_deployment_multi_tenant_app_client_id) != lower(var.onboarding.multi_tenant_app_client_id)
    error_message = "customerOnboarding.o11y_deployment_multi_tenant_app_client_id must not equal multi_tenant_app_client_id; the regional-control-plane app cannot be reused for O11Y deployment."
  }
}

check "onboarding_o11y_resource_groups" {
  assert {
    condition     = try(trimspace(var.onboarding.o11y_aks_resource_group) != "", false)
    error_message = "customerOnboarding.o11y_aks_resource_group must be set to the onboarding-created O11Y AKS resource group."
  }

  assert {
    condition     = try(trimspace(var.onboarding.o11y_storage_resource_group) != "", false)
    error_message = "customerOnboarding.o11y_storage_resource_group must be set to the onboarding-created O11Y storage resource group."
  }
}

check "onboarding_o11y_identity_names" {
  assert {
    condition = alltrue([
      for name in values(local.required_o11y_identity_names) : name != "" && !strcontains(name, "/")
    ])
    error_message = "customerOnboarding O11Y identity names are required for regional_server, vmbackup, loki, velero, and agic and must be Azure user-assigned managed identity names, not ARM resource IDs."
  }

}

check "onboarding_o11y_aks_identity_names" {
  assert {
    condition = alltrue([
      for name in values(local.o11y_aks_identity_names) : name != "" && !strcontains(name, "/")
    ])
    error_message = "customerOnboarding O11Y AKS identity names are required for control_plane and kubelet and must be Azure user-assigned managed identity names, not ARM resource IDs."
  }
}

check "onboarding_o11y_identity_resource_group" {
  assert {
    condition     = local.o11y_identity_resource_group != "" && !strcontains(local.o11y_identity_resource_group, "/")
    error_message = "customerOnboarding.o11y_identity_resource_group must be the Azure resource group name containing all O11Y user-assigned managed identities."
  }
}

check "seed_controlplane_defaults_found" {
  assert {
    condition     = local.base_account != ""
    error_message = "No base_account found in azure/account/seed state for this env."
  }

  assert {
    condition     = local.controlplane_tenant_id != ""
    error_message = "No controlplane_tenant_id found in azure/account/seed state for this env."
  }

  assert {
    condition     = local.controlplane_subscription != ""
    error_message = "No controlplane_subscription_id found in azure/account/seed state for this env."
  }

  assert {
    condition     = local.controlplane_client_id != ""
    error_message = "No controlplane_client_id found in azure/account/seed state for this env."
  }

  assert {
    condition     = local.image_registry != ""
    error_message = "No image_registry found in azure/account/seed state for this env."
  }

  assert {
    condition     = local.effective_acr_id_scope != ""
    error_message = "No acr_id_scope found in azure/account/seed state for this env."
  }

  assert {
    condition     = length(local.control_plane_admin_group_object_ids) > 0
    error_message = "No admin_group_object_ids found in azure/account/seed state for this env."
  }
}

check "o11y_global_defaults_found" {
  assert {
    condition     = try(local.o11y_outputs.account.value, "") != ""
    error_message = "No account output found in aws/o11y-global/prod.json state."
  }

  assert {
    condition     = try(local.o11y_outputs.sns_topic_arn.value, "") != ""
    error_message = "No sns_topic_arn output found in aws/o11y-global/prod.json state."
  }
}

check "o11y_dns_zone_found" {
  assert {
    condition     = local.o11y_dns_zone_requested_name != "" && !strcontains(local.o11y_dns_zone_requested_name, "/")
    error_message = "customerOnboarding.o11y_dns_domain must be the Azure DNS zone name for O11Y RS/DS records, not an ARM resource ID."
  }

  assert {
    condition     = local.o11y_dns_zone_requested_resource_group_name != "" && !strcontains(local.o11y_dns_zone_requested_resource_group_name, "/")
    error_message = "customerOnboarding.o11y_dns_resource_group must be the Azure resource group containing the O11Y DNS zone, not an ARM resource ID."
  }

  assert {
    condition     = lower(local.o11y_dns_zone_resource_id) == lower("/subscriptions/${var.onboarding.customer_subscription_id}/resourceGroups/${local.o11y_dns_zone_requested_resource_group_name}/providers/Microsoft.Network/dnsZones/${local.o11y_dns_zone_requested_name}")
    error_message = "Azure DNS zone resolved from customerOnboarding.o11y_dns_domain and customerOnboarding.o11y_dns_resource_group must be in customer_subscription_id."
  }
}

data "external" "controlplane_dns_zone" {
  program = ["bash", "-lc", <<-EOT
    set -euo pipefail
    rg=$(az network dns zone list --subscription '${local.controlplane_subscription}' --query "[?name=='${local.controlplane_domain}'].resourceGroup | [0]" -o tsv)
    printf '{"resource_group_name":"%s"}\n' "$rg"
  EOT
  ]

  lifecycle {
    postcondition {
      condition     = self.result.resource_group_name != ""
      error_message = "Azure DNS zone ${local.controlplane_domain} not found in the current subscription."
    }
  }
}

data "external" "dataplane_dns_zone" {
  program = ["bash", "-lc", <<-EOT
    set -euo pipefail
    rg=$(az network dns zone list --subscription '${local.controlplane_subscription}' --query "[?name=='${local.dataplane_domain_name}'].resourceGroup | [0]" -o tsv)
    printf '{"resource_group_name":"%s"}\n' "$rg"
  EOT
  ]

  lifecycle {
    postcondition {
      condition     = self.result.resource_group_name != ""
      error_message = "Azure DNS zone ${local.dataplane_domain_name} not found in the current subscription."
    }
  }
}
