locals {
  google_required_services = toset([
    "cloudkms.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "iam.googleapis.com",
    "iamcredentials.googleapis.com",
    "sts.googleapis.com",
  ])

  google_existing_kms_key_ring_id = var.google_kms_key_ring_id != "" ? var.google_kms_key_ring_id : "projects/${var.google_project_id}/locations/${var.google_kms_key_ring_location}/keyRings/${var.google_kms_key_ring_name}"

  google_kms_key_ring_id = var.manage_google_kms_key_ring ? (
    google_kms_key_ring.identity[0].id
  ) : local.google_existing_kms_key_ring_id

  google_runner_service_account_email = var.manage_google_runner_service_account ? (
    google_service_account.runner[0].email
  ) : var.google_runner_service_account_email

  google_runner_wif_group_members = var.google_wif_runner_group != "" ? (
    toset([
      "principalSet://iam.googleapis.com/projects/${var.google_project_number}/locations/global/workloadIdentityPools/${var.google_wif_pool_id}/group/${var.google_wif_runner_group}"
    ])
    ) : (
    toset([])
  )

  google_runner_wif_client_members = var.google_wif_runner_client_id != "" ? (
    toset([
      "principalSet://iam.googleapis.com/projects/${var.google_project_number}/locations/global/workloadIdentityPools/${var.google_wif_pool_id}/attribute.burrow_client_id/${var.google_wif_runner_client_id}"
    ])
    ) : (
    toset([])
  )

  google_runner_wif_members = setunion(
    local.google_runner_wif_group_members,
    local.google_runner_wif_client_members,
    var.google_wif_runner_group == "" && var.google_wif_runner_client_id == "" ? toset([
      "principalSet://iam.googleapis.com/projects/${var.google_project_number}/locations/global/workloadIdentityPools/${var.google_wif_pool_id}/*"
    ]) : toset([])
  )

  google_signer_members = setunion(
    var.google_release_signer_members,
    toset(["serviceAccount:${local.google_runner_service_account_email}"]),
  )

  google_signer_grants = var.manage_google ? {
    for grant in flatten([
      for key_name in keys(google_kms_crypto_key.signing) : [
        for member in local.google_signer_members : {
          id       = "${key_name}|${member}"
          key_name = key_name
          member   = member
        }
      ]
    ]) : grant.id => grant
  } : {}
}

resource "google_project_service" "identity" {
  for_each = var.manage_google ? local.google_required_services : toset([])

  project            = var.google_project_id
  service            = each.value
  disable_on_destroy = false
}

resource "google_kms_key_ring" "identity" {
  count = var.manage_google && var.manage_google_kms_key_ring ? 1 : 0

  project  = var.google_project_id
  location = var.google_kms_key_ring_location
  name     = var.google_kms_key_ring_name

  depends_on = [google_project_service.identity]
}

resource "google_kms_crypto_key" "signing" {
  for_each = var.manage_google && local.google_kms_key_ring_id != "" ? var.google_signing_keys : {}

  name     = each.value.name
  key_ring = local.google_kms_key_ring_id
  purpose  = "ASYMMETRIC_SIGN"
  labels = merge(
    {
      project    = "burrow"
      component  = "identity"
      managed_by = "opentofu"
    },
    var.tags,
    try(each.value.labels, {}),
  )

  version_template {
    algorithm        = try(each.value.algorithm, "RSA_SIGN_PKCS1_2048_SHA256")
    protection_level = try(each.value.protection_level, "HSM")
  }

  lifecycle {
    prevent_destroy = true
  }
}

resource "google_service_account" "runner" {
  count = var.manage_google && var.manage_google_runner_service_account ? 1 : 0

  project      = var.google_project_id
  account_id   = var.google_runner_service_account_id
  display_name = "Burrow Forgejo Runner"
  description  = "Authentik-backed WIF service account for Burrow Forgejo runners."

  depends_on = [google_project_service.identity]
}

resource "google_iam_workload_identity_pool" "burrow" {
  count = var.manage_google ? 1 : 0

  project                   = var.google_project_id
  workload_identity_pool_id = var.google_wif_pool_id
  display_name              = "Burrow Authentik"
  description               = "Authentik-issued identities for Burrow automation."
  disabled                  = false

  depends_on = [google_project_service.identity]
}

resource "google_iam_workload_identity_pool_provider" "forgejo_runners" {
  count = var.manage_google ? 1 : 0

  project                            = var.google_project_id
  workload_identity_pool_id          = google_iam_workload_identity_pool.burrow[0].workload_identity_pool_id
  workload_identity_pool_provider_id = var.google_wif_provider_id
  display_name                       = "Burrow Forgejo Runners"
  description                        = "Authentik OIDC provider for Burrow Forgejo runner cloud access."
  disabled                           = false

  attribute_mapping = {
    "google.subject"             = "assertion.sub"
    "google.groups"              = "assertion.groups"
    "attribute.burrow_subject"   = "assertion.sub"
    "attribute.burrow_username"  = "assertion.preferred_username"
    "attribute.burrow_email"     = "assertion.email"
    "attribute.burrow_client_id" = "assertion.aud"
  }

  attribute_condition = var.google_wif_attribute_condition

  oidc {
    issuer_uri        = var.google_wif_issuer_uri
    allowed_audiences = var.google_wif_allowed_audiences
  }
}

resource "google_service_account_iam_member" "runner_wif" {
  for_each = var.manage_google ? local.google_runner_wif_members : toset([])

  service_account_id = var.manage_google_runner_service_account ? (
    google_service_account.runner[0].name
  ) : "projects/${var.google_project_id}/serviceAccounts/${local.google_runner_service_account_email}"
  role   = "roles/iam.workloadIdentityUser"
  member = each.value
}

resource "google_kms_crypto_key_iam_member" "signer" {
  for_each = local.google_signer_grants

  crypto_key_id = google_kms_crypto_key.signing[each.value.key_name].id
  role          = "roles/cloudkms.signerVerifier"
  member        = each.value.member
}
