# Networking Module for Azure
# Creates VNet, subnets, NSGs, and Application Gateway

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

# Subnet for AKS
resource "azurerm_subnet" "aks" {
  name                 = "${var.cluster_name}-aks-subnet"
  resource_group_name  = var.resource_group_name
  virtual_network_name = azurerm_virtual_network.main.name
  address_prefixes     = ["10.0.1.0/24"]
  
  # Required for AKS
  service_endpoints = ["Microsoft.Storage", "Microsoft.KeyVault"]
}

# Subnet for validators (private)
resource "azurerm_subnet" "validators" {
  name                 = "${var.cluster_name}-validators-subnet"
  resource_group_name  = var.resource_group_name
  virtual_network_name = azurerm_virtual_network.main.name
  address_prefixes     = ["10.0.2.0/24"]
  
  # No service endpoints for private subnet
}

# Subnet for sentries (public P2P)
resource "azurerm_subnet" "sentries" {
  name                 = "${var.cluster_name}-sentries-subnet"
  resource_group_name  = var.resource_group_name
  virtual_network_name = azurerm_virtual_network.main.name
  address_prefixes     = ["10.0.3.0/24"]
}

# Subnet for RPC nodes (DMZ)
resource "azurerm_subnet" "rpc" {
  name                 = "${var.cluster_name}-rpc-subnet"
  resource_group_name  = var.resource_group_name
  virtual_network_name = azurerm_virtual_network.main.name
  address_prefixes     = ["10.0.4.0/24"]
  
  service_endpoints = ["Microsoft.Storage"]
}

# Subnet for Application Gateway
resource "azurerm_subnet" "appgateway" {
  name                 = "${var.cluster_name}-appgateway-subnet"
  resource_group_name  = var.resource_group_name
  virtual_network_name = azurerm_virtual_network.main.name
  address_prefixes     = ["10.0.5.0/24"]
}

# Network Security Group for validators (private, no public access)
resource "azurerm_network_security_group" "validators" {
  name                = "${var.cluster_name}-validators-nsg"
  location            = var.location
  resource_group_name = var.resource_group_name
  
  # Allow internal communication only
  security_rule {
    name                       = "AllowInternal"
    priority                   = 1000
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "*"
    source_port_range          = "*"
    destination_port_range     = "*"
    source_address_prefix      = "10.0.0.0/16"
    destination_address_prefix = "*"
  }
  
  # Deny all other traffic
  security_rule {
    name                       = "DenyAll"
    priority                   = 4096
    direction                  = "Inbound"
    access                     = "Deny"
    protocol                   = "*"
    source_port_range          = "*"
    destination_port_range     = "*"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
  
  tags = merge(var.tags, {
    Purpose = "Validators-NSG"
  })
}

# Network Security Group for sentries (P2P port 30303)
resource "azurerm_network_security_group" "sentries" {
  name                = "${var.cluster_name}-sentries-nsg"
  location            = var.location
  resource_group_name = var.resource_group_name
  
  # Allow P2P (30303 TCP/UDP)
  security_rule {
    name                       = "AllowP2P"
    priority                   = 1000
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "30303"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
  
  security_rule {
    name                       = "AllowP2PUDP"
    priority                   = 1001
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Udp"
    source_port_range          = "*"
    destination_port_range     = "30303"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
  
  # Allow internal communication
  security_rule {
    name                       = "AllowInternal"
    priority                   = 2000
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "*"
    source_port_range          = "*"
    destination_port_range     = "*"
    source_address_prefix      = "10.0.0.0/16"
    destination_address_prefix = "*"
  }
  
  tags = merge(var.tags, {
    Purpose = "Sentries-NSG"
  })
}

# Network Security Group for RPC (HTTPS only)
resource "azurerm_network_security_group" "rpc" {
  name                = "${var.cluster_name}-rpc-nsg"
  location            = var.location
  resource_group_name = var.resource_group_name
  
  # Allow HTTPS (443)
  security_rule {
    name                       = "AllowHTTPS"
    priority                   = 1000
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "443"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
  
  # Allow HTTP (for redirect to HTTPS)
  security_rule {
    name                       = "AllowHTTP"
    priority                   = 1001
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "80"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
  
  # Allow internal communication
  security_rule {
    name                       = "AllowInternal"
    priority                   = 2000
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "*"
    source_port_range          = "*"
    destination_port_range     = "*"
    source_address_prefix      = "10.0.0.0/16"
    destination_address_prefix = "*"
  }
  
  tags = merge(var.tags, {
    Purpose = "RPC-NSG"
  })
}

# Associate NSGs with subnets
resource "azurerm_subnet_network_security_group_association" "validators" {
  subnet_id                 = azurerm_subnet.validators.id
  network_security_group_id = azurerm_network_security_group.validators.id
}

resource "azurerm_subnet_network_security_group_association" "sentries" {
  subnet_id                 = azurerm_subnet.sentries.id
  network_security_group_id = azurerm_network_security_group.sentries.id
}

resource "azurerm_subnet_network_security_group_association" "rpc" {
  subnet_id                 = azurerm_subnet.rpc.id
  network_security_group_id = azurerm_network_security_group.rpc.id
}

# Public IP for Application Gateway
resource "azurerm_public_ip" "appgateway" {
  name                = "${var.cluster_name}-appgateway-ip"
  location            = var.location
  resource_group_name = var.resource_group_name
  allocation_method   = "Static"
  sku                 = "Standard"
  
  tags = merge(var.tags, {
    Purpose = "Application-Gateway-IP"
  })
}

# Application Gateway (simplified - full config would include backend pools, listeners, etc.)
resource "azurerm_application_gateway" "main" {
  name                = "${var.cluster_name}-appgateway"
  resource_group_name = var.resource_group_name
  location            = var.location
  
  sku {
    name     = "WAF_v2"
    tier     = "WAF_v2"
    capacity = 2
  }
  
  gateway_ip_configuration {
    name      = "appGatewayIpConfig"
    subnet_id = azurerm_subnet.appgateway.id
  }
  
  frontend_port {
    name = "http"
    port = 80
  }
  
  frontend_port {
    name = "https"
    port = 443
  }
  
  frontend_ip_configuration {
    name                 = "appGatewayFrontendIP"
    public_ip_address_id = azurerm_public_ip.appgateway.id
  }
  
  # SSL Policy (required for WAF_v2)
  ssl_policy {
    policy_type = "Predefined"
    policy_name = "AppGwSslPolicy20220101"  # Modern TLS policy
  }

  # WAF configuration
  waf_configuration {
    enabled                  = true
    firewall_mode            = "Prevention"
    rule_set_type            = "OWASP"
    rule_set_version         = "3.2"
    file_upload_limit_mb     = 100
    request_body_check       = true
    max_request_body_size_kb = 128
  }

  # Minimal required blocks - will be configured after AKS deployment
  backend_address_pool {
    name = "default-backend-pool"
    # Backend IPs will be added after AKS services are deployed
  }

  backend_http_settings {
    name                  = "default-http-settings"
    cookie_based_affinity = "Disabled"
    port                  = 80
    protocol              = "Http"
    request_timeout       = 20
  }

  http_listener {
    name                           = "default-listener"
    frontend_ip_configuration_name = "appGatewayFrontendIP"
    frontend_port_name             = "http"
    protocol                       = "Http"
  }

  request_routing_rule {
    name                       = "default-routing-rule"
    rule_type                  = "Basic"
    priority                   = 100
    http_listener_name         = "default-listener"
    backend_address_pool_name  = "default-backend-pool"
    backend_http_settings_name = "default-http-settings"
  }
  
  # Note: Backend pools, HTTP settings, probes, listeners, and routing rules
  # should be reconfigured after AKS deployment when service IPs are known.
  # Use Azure CLI or Terraform to update these resources after initial deployment.
  #
  # For production, consider using Azure Application Gateway Ingress Controller (AGIC)
  # which automatically configures the Application Gateway based on Kubernetes ingress resources.
  
  tags = merge(var.tags, {
    Purpose = "Application-Gateway"
  })
}

# Outputs are defined in outputs.tf
