locals {
  provided_identity_names = {
    regional_server = trimspace(var.o11y_regional_server_identity_name)
    vmbackup        = trimspace(var.o11y_vmbackup_identity_name)
    loki            = trimspace(var.o11y_loki_identity_name)
    velero          = trimspace(var.o11y_velero_identity_name)
    agic            = trimspace(var.o11y_agic_identity_name)
  }

  identity_names = {
    regional_server = local.provided_identity_names.regional_server
    vmbackup        = local.provided_identity_names.vmbackup
    loki            = local.provided_identity_names.loki
    velero          = local.provided_identity_names.velero
    agic            = local.provided_identity_names.agic
    drhouse         = local.provided_identity_names.regional_server
    ops_server      = local.provided_identity_names.regional_server
  }

  required_identity_names = {
    regional_server = local.identity_names.regional_server
    vmbackup        = local.identity_names.vmbackup
    loki            = local.identity_names.loki
    velero          = local.identity_names.velero
    agic            = local.identity_names.agic
  }

  required_service_account_subjects = {
    regional_server = "system:serviceaccount:observability:regional-server-controller-manager"
    vmbackup        = "system:serviceaccount:observability:vmcluster-vmcluster"
    loki            = "system:serviceaccount:observability:loki-ha"
    velero          = "system:serviceaccount:cluster-backup:velero-server"
    agic            = "system:serviceaccount:kube-system:ingress-azure"
    drhouse         = "system:serviceaccount:observability:diagnosis-query"
    ops_server      = "system:serviceaccount:ops-system:ops-server"
  }

  valid_identity_names = {
    for name, identity_name in local.identity_names : name => identity_name
    if identity_name != "" && !strcontains(identity_name, "/")
  }

  identity_resource_ids = {
    for name in keys(local.identity_names) : name => try(data.azurerm_user_assigned_identity.o11y[name].id, "")
  }

  identity_client_ids = {
    for name in keys(local.identity_names) : name => try(data.azurerm_user_assigned_identity.o11y[name].client_id, "")
  }

  required_identity_client_ids = {
    regional_server = local.identity_client_ids.regional_server
    vmbackup        = local.identity_client_ids.vmbackup
    loki            = local.identity_client_ids.loki
    velero          = local.identity_client_ids.velero
    agic            = local.identity_client_ids.agic
  }

  federated_identity_credentials = {
    for name, subject in local.required_service_account_subjects : name => {
      name      = "fic-${replace(name, "_", "-")}"
      parent_id = local.identity_resource_ids[name]
      subject   = subject
    }
    if contains(keys(local.valid_identity_names), name)
  }
}

data "azurerm_user_assigned_identity" "o11y" {
  for_each = local.valid_identity_names

  name                = each.value
  resource_group_name = var.o11y_identity_resource_group
}

resource "null_resource" "o11y_identity_prerequisites" {
  depends_on = [module.aks]

  triggers = merge(
    {
      oidc_issuer = module.aks.oidc_issuer
    },
    { for name, subject in local.required_service_account_subjects : "subject_${name}" => subject },
    { for name, client_id in local.identity_client_ids : "client_id_${name}" => client_id },
    { for name, resource_id in local.identity_resource_ids : "resource_id_${name}" => resource_id },
    { for name, identity_name in local.identity_names : "name_${name}" => identity_name },
    {
      resource_group_name = var.o11y_identity_resource_group
    },
  )

  lifecycle {
    precondition {
      condition = alltrue([
        for identity_name in values(local.required_identity_names) : identity_name != "" && !strcontains(identity_name, "/")
      ])
      error_message = "Azure BYOC O11Y identity names are required after AKS publishes its OIDC issuer. Populate the flat onboarding o11y_identity_*_name fields with onboarding-owned user-assigned managed identity names."
    }

    precondition {
      condition = alltrue([
        for client_id in values(local.required_identity_client_ids) : client_id != ""
      ])
      error_message = "Azure BYOC O11Y identity client IDs could not be resolved from the provided user-assigned managed identity names and O11Y managed identity resource group."
    }
  }
}

resource "azurerm_federated_identity_credential" "o11y" {
  for_each = local.federated_identity_credentials

  name      = each.value.name
  parent_id = each.value.parent_id
  audience            = ["api://AzureADTokenExchange"]
  issuer              = module.aks.oidc_issuer
  subject             = each.value.subject

  depends_on = [null_resource.o11y_identity_prerequisites]
}
