# Networking Module for VM Deployment (Phase 1)
# Creates VNet, subnets, NSGs for VM-based deployment

# Virtual Network
resource "azurerm_virtual_network" "main" {
  name                = "${var.cluster_name}-vnet"
  address_space       = [var.vnet_address_space]
  location            = var.location
  resource_group_name = var.resource_group_name
  
  tags = merge(var.tags, {
    Purpose = "Networking"
  })
}

# Subnet for VMs
resource "azurerm_subnet" "vm" {
  name                 = "${var.cluster_name}-vm-subnet"
  resource_group_name  = var.resource_group_name
  virtual_network_name = azurerm_virtual_network.main.name
  address_prefixes     = [var.subnet_address_prefix]
  
  service_endpoints = ["Microsoft.Storage", "Microsoft.KeyVault"]
}

# Network Security Group for VMs
resource "azurerm_network_security_group" "vm" {
  name                = "${var.cluster_name}-vm-nsg"
  location            = var.location
  resource_group_name = var.resource_group_name
  
  # Allow SSH (restrict to specific IPs in production)
  security_rule {
    name                       = "AllowSSH"
    priority                   = 1000
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = length(var.allowed_ssh_ips) > 0 ? null : "*"
    source_address_prefixes   = length(var.allowed_ssh_ips) > 0 ? var.allowed_ssh_ips : null
    destination_address_prefix = "*"
    description                = length(var.allowed_ssh_ips) > 0 ? "Allow SSH access from specified IPs" : "Allow SSH access from anywhere (WARNING: Not secure for production)"
  }
  
  # Allow P2P (Besu) - TCP (only for Besu nodes, not Nginx proxy)
  dynamic "security_rule" {
    for_each = var.enable_besu_rules ? [1] : []
    content {
      name                       = "AllowP2PTCP"
      priority                   = 1001
      direction                  = "Inbound"
      access                     = "Allow"
      protocol                   = "Tcp"
      source_port_range          = "*"
      destination_port_range     = "30303"
      source_address_prefix      = length(var.allowed_p2p_ips) > 0 ? null : "*"
      source_address_prefixes   = length(var.allowed_p2p_ips) > 0 ? var.allowed_p2p_ips : null
      destination_address_prefix = "*"
      description                = length(var.allowed_p2p_ips) > 0 ? "Allow Besu P2P TCP from specified IPs" : "Allow Besu P2P TCP from anywhere (WARNING: Not secure for production)"
    }
  }
  
  # Allow P2P (Besu) - UDP (only for Besu nodes, not Nginx proxy)
  dynamic "security_rule" {
    for_each = var.enable_besu_rules ? [1] : []
    content {
      name                       = "AllowP2PUDP"
      priority                   = 1002
      direction                  = "Inbound"
      access                     = "Allow"
      protocol                   = "Udp"
      source_port_range          = "*"
      destination_port_range     = "30303"
      source_address_prefix      = length(var.allowed_p2p_ips) > 0 ? null : "*"
      source_address_prefixes   = length(var.allowed_p2p_ips) > 0 ? var.allowed_p2p_ips : null
      destination_address_prefix = "*"
      description                = length(var.allowed_p2p_ips) > 0 ? "Allow Besu P2P UDP from specified IPs" : "Allow Besu P2P UDP from anywhere (WARNING: Not secure for production)"
    }
  }
  
  # Allow RPC HTTP (from Nginx proxy via VPN/ExpressRoute)
  # NOTE: Backend VMs use private IPs only. Nginx proxy connects via VPN/ExpressRoute.
  # Restrict to Nginx proxy private IP subnet once VPN is deployed.
  # Only for Besu nodes, not Nginx proxy
  dynamic "security_rule" {
    for_each = var.enable_besu_rules ? [1] : []
    content {
      name                       = "AllowRPCHTTP"
      priority                   = 1003
      direction                  = "Inbound"
      access                     = "Allow"
      protocol                   = "Tcp"
      source_port_range          = "*"
      destination_port_range     = "8545"
      source_address_prefix      = length(var.allowed_rpc_ips) > 0 ? null : "*"
      source_address_prefixes   = length(var.allowed_rpc_ips) > 0 ? var.allowed_rpc_ips : null
      destination_address_prefix = "*"
      description                = length(var.allowed_rpc_ips) > 0 ? "Allow RPC HTTP from specified IPs (Nginx proxy subnet or Cloudflare Tunnel IPs)" : "Allow RPC HTTP from anywhere (WARNING: Not secure for production)"
    }
  }
  
  # Allow RPC WebSocket (from Nginx proxy via VPN/ExpressRoute)
  # NOTE: Backend VMs use private IPs only. Nginx proxy connects via VPN/ExpressRoute.
  # Restrict to Nginx proxy private IP subnet once VPN is deployed.
  # Only for Besu nodes, not Nginx proxy
  dynamic "security_rule" {
    for_each = var.enable_besu_rules ? [1] : []
    content {
      name                       = "AllowRPCWS"
      priority                   = 1004
      direction                  = "Inbound"
      access                     = "Allow"
      protocol                   = "Tcp"
      source_port_range          = "*"
      destination_port_range     = "8546"
      source_address_prefix      = length(var.allowed_rpc_ips) > 0 ? null : "*"
      source_address_prefixes   = length(var.allowed_rpc_ips) > 0 ? var.allowed_rpc_ips : null
      destination_address_prefix = "*"
      description                = length(var.allowed_rpc_ips) > 0 ? "Allow RPC WebSocket from specified IPs (Nginx proxy subnet or Cloudflare Tunnel IPs)" : "Allow RPC WebSocket from anywhere (WARNING: Not secure for production)"
    }
  }
  
  # Allow Metrics (only for Besu nodes, not Nginx proxy)
  dynamic "security_rule" {
    for_each = var.enable_besu_rules ? [1] : []
    content {
      name                       = "AllowMetrics"
      priority                   = 1005
      direction                  = "Inbound"
      access                     = "Allow"
      protocol                   = "Tcp"
      source_port_range          = "*"
      destination_port_range     = "9545"
      source_address_prefix      = length(var.allowed_metrics_ips) > 0 ? null : "*"
      source_address_prefixes   = length(var.allowed_metrics_ips) > 0 ? var.allowed_metrics_ips : null
      destination_address_prefix = "*"
      description                = length(var.allowed_metrics_ips) > 0 ? "Allow Prometheus metrics from specified IPs" : "Allow Prometheus metrics from anywhere (WARNING: Not secure for production)"
    }
  }
  
  # Allow outbound internet access
  security_rule {
    name                       = "AllowOutboundInternet"
    priority                   = 2000
    direction                  = "Outbound"
    access                     = "Allow"
    protocol                   = "*"
    source_port_range          = "*"
    destination_port_range     = "*"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
    description                = "Allow outbound internet access"
  }
  
  tags = merge(var.tags, {
    Purpose = "Network-Security"
  })
}

# Associate NSG with VM subnet (only if subnet_nsg_enabled is true)
# For Nginx proxy subnet, we don't need subnet-level NSG (NIC-level NSG is sufficient)
resource "azurerm_subnet_network_security_group_association" "vm" {
  count                     = var.subnet_nsg_enabled ? 1 : 0
  subnet_id                 = azurerm_subnet.vm.id
  network_security_group_id = azurerm_network_security_group.vm.id
}

# Outputs
output "vm_subnet_id" {
  value = azurerm_subnet.vm.id
  description = "Subnet ID for VMs"
}

output "vm_nsg_id" {
  value = azurerm_network_security_group.vm.id
  description = "Network Security Group ID for VMs"
}

output "vnet_id" {
  value = azurerm_virtual_network.main.id
  description = "Virtual Network ID"
}

