resource "azurerm_resource_group" "this" {
  name     = "${local.deployment_name}-rg"
  location = var.azure_location
  tags     = local.tags

  lifecycle {
    precondition {
      condition     = data.azurerm_subscription.current.display_name == var.azure_subscription_name
      error_message = "azure_subscription_id does not match azure_subscription_name."
    }
  }
}

resource "azurerm_virtual_network" "this" {
  name                = "${local.deployment_name}-vnet"
  location            = azurerm_resource_group.this.location
  resource_group_name = azurerm_resource_group.this.name
  address_space       = [var.vnet_cidr]
  tags                = local.tags
}

resource "azurerm_subnet" "services" {
  name                 = "services"
  resource_group_name  = azurerm_resource_group.this.name
  virtual_network_name = azurerm_virtual_network.this.name
  address_prefixes     = [cidrsubnet(var.vnet_cidr, 4, 0)]
}

resource "azurerm_subnet" "private_link_service" {
  name                                          = "private-link-service-nat"
  resource_group_name                           = azurerm_resource_group.this.name
  virtual_network_name                          = azurerm_virtual_network.this.name
  address_prefixes                              = [cidrsubnet(var.vnet_cidr, 4, 1)]
  private_link_service_network_policies_enabled = false
}

resource "azurerm_network_security_group" "services" {
  name                = "${local.deployment_name}-services"
  location            = azurerm_resource_group.this.location
  resource_group_name = azurerm_resource_group.this.name
  tags                = local.tags
}

resource "azurerm_network_security_rule" "private_services" {
  for_each = {
    mysql     = local.ports.mysql
    anonymous = local.ports.kafka_pl_public
    sasl      = local.ports.kafka_pl_sasl
  }

  name                        = "private-services-${each.key}"
  priority                    = 300 + index(sort(keys({ mysql = local.ports.mysql, anonymous = local.ports.kafka_pl_public, sasl = local.ports.kafka_pl_sasl })), each.key)
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "Tcp"
  source_port_range           = "*"
  destination_port_range      = tostring(each.value)
  source_address_prefix       = azurerm_subnet.private_link_service.address_prefixes[0]
  destination_address_prefix  = "*"
  resource_group_name         = azurerm_resource_group.this.name
  network_security_group_name = azurerm_network_security_group.services.name
}

resource "azurerm_network_security_rule" "load_balancer_probes" {
  name              = "azure-load-balancer-probes"
  priority          = 350
  direction         = "Inbound"
  access            = "Allow"
  protocol          = "Tcp"
  source_port_range = "*"
  destination_port_ranges = [
    tostring(local.ports.mysql),
    tostring(local.ports.kafka_pl_public),
    tostring(local.ports.kafka_pl_sasl),
  ]
  source_address_prefix       = "AzureLoadBalancer"
  destination_address_prefix  = "*"
  resource_group_name         = azurerm_resource_group.this.name
  network_security_group_name = azurerm_network_security_group.services.name
}

resource "azurerm_public_ip" "services" {
  name                = "${local.deployment_name}-public"
  location            = azurerm_resource_group.this.location
  resource_group_name = azurerm_resource_group.this.name
  allocation_method   = "Static"
  sku                 = "Standard"
  tags                = local.tags
}

resource "azurerm_network_interface" "services" {
  name                = "${local.deployment_name}-services"
  location            = azurerm_resource_group.this.location
  resource_group_name = azurerm_resource_group.this.name
  tags                = local.tags

  ip_configuration {
    name                          = "primary"
    subnet_id                     = azurerm_subnet.services.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.services.id
  }
}

resource "azurerm_network_interface_security_group_association" "services" {
  network_interface_id      = azurerm_network_interface.services.id
  network_security_group_id = azurerm_network_security_group.services.id
}
