# On-Premises HCI Infrastructure Module
# Supports Azure Stack HCI and vSphere-based HCI clusters

locals {
  env = var.environment_config
  
  # Extract on-prem config
  onprem_config = try(local.env.onprem, {})
  hci_config = try(local.env.azure_stack_hci, {})
  
  # Extract infrastructure config
  infra = try(local.env.infrastructure, {})
  k8s_config = try(local.infra.kubernetes, {})
  hci_k8s = try(local.k8s_config.hci, {})
  
  # Naming
  name_prefix = "${local.env.name}-${var.environment}"
  
  # HCI platform
  hci_platform = try(local.onprem_config.hci_platform, "azure-stack-hci")
  
  # Node pools
  node_pools = try(local.hci_k8s.node_pools, {})
}

# ============================================
# AZURE STACK HCI
# ============================================
# Azure Stack HCI uses Azure Arc to manage Kubernetes clusters
# The cluster is pre-provisioned on-prem, we just onboard it to Azure Arc

resource "azapi_resource" "azure_stack_hci_cluster" {
  count = local.hci_platform == "azure-stack-hci" && try(local.hci_config.enabled, false) ? 1 : 0
  
  type      = "Microsoft.Kubernetes/connectedClusters@2023-11-01-preview"
  name      = try(local.hci_config.cluster_name, "${local.name_prefix}-hci")
  location  = try(local.hci_config.location, "westus")  # Azure region for Arc resource
  
  parent_id = "/subscriptions/${var.azure_subscription_id}/resourceGroups/${try(local.hci_config.resource_group, "rg-hci-${var.environment}")}"
  
  body = jsonencode({
    properties = {
      agentPublicKeyCertificate = ""  # Will be populated by Arc agent installed on-prem
      distribution              = "AKS"
      infrastructure            = "azure_stack_hci"
    }
  })
  
  tags = var.tags
}

# ============================================
# VSPHERE-BASED HCI
# ============================================
# For vSphere, we provision VMs and install Kubernetes

# Data sources for vSphere
data "vsphere_datacenter" "dc" {
  count = local.hci_platform == "vsphere" ? 1 : 0
  name  = try(local.onprem_config.datacenter, "datacenter1")
}

data "vsphere_datastore" "datastore" {
  count         = local.hci_platform == "vsphere" ? 1 : 0
  name          = try(local.onprem_config.datastore, "datastore1")
  datacenter_id = data.vsphere_datacenter.dc[0].id
}

data "vsphere_compute_cluster" "cluster" {
  count         = local.hci_platform == "vsphere" ? 1 : 0
  name          = try(local.onprem_config.cluster, "cluster1")
  datacenter_id = data.vsphere_datacenter.dc[0].id
}

data "vsphere_network" "network" {
  count         = local.hci_platform == "vsphere" ? 1 : 0
  name          = try(local.onprem_config.network, "VM Network")
  datacenter_id = data.vsphere_datacenter.dc[0].id
}

data "vsphere_virtual_machine" "template" {
  count         = local.hci_platform == "vsphere" ? 1 : 0
  name          = try(local.onprem_config.vm_template, "ubuntu-22.04-template")
  datacenter_id = data.vsphere_datacenter.dc[0].id
}

# System nodes
resource "vsphere_virtual_machine" "system" {
  count            = local.hci_platform == "vsphere" && try(local.node_pools.system.count, 0) > 0 ? local.node_pools.system.count : 0
  name             = "${local.name_prefix}-system-${count.index + 1}"
  resource_pool_id = data.vsphere_compute_cluster.cluster[0].resource_pool_id
  datastore_id     = data.vsphere_datastore.datastore[0].id
  
  num_cpus               = 2
  memory                  = 4096
  guest_id                = data.vsphere_virtual_machine.template[0].guest_id
  scsi_type               = data.vsphere_virtual_machine.template[0].scsi_type
  firmware                = data.vsphere_virtual_machine.template[0].firmware
  
  network_interface {
    network_id = data.vsphere_network.network[0].id
  }
  
  disk {
    label            = "disk0"
    size             = 100
    eagerly_scrub    = false
    thin_provisioned = true
  }
  
  clone {
    template_uuid = data.vsphere_virtual_machine.template[0].id
    
    customize {
      linux_options {
        host_name = "${local.name_prefix}-system-${count.index + 1}"
        domain    = try(local.env.identity.domain, "local")
      }
      
      network_interface {
        ipv4_address = cidrhost(try(local.env.infrastructure.networking.subnet_cidr, "192.168.1.0/24"), count.index + 10)
        ipv4_netmask = 24
      }
      
      ipv4_gateway    = try(local.env.infrastructure.networking.gateway, "192.168.1.1")
      dns_server_list = ["8.8.8.8", "8.8.4.4"]
    }
  }
  
  tags = [for k, v in var.tags : "${k}=${v}"]
}

# Validator nodes
resource "vsphere_virtual_machine" "validators" {
  count            = local.hci_platform == "vsphere" && try(local.node_pools.validators.count, 0) > 0 ? local.node_pools.validators.count : 0
  name             = "${local.name_prefix}-validator-${count.index + 1}"
  resource_pool_id = data.vsphere_compute_cluster.cluster[0].resource_pool_id
  datastore_id     = data.vsphere_datastore.datastore[0].id
  
  num_cpus               = 4
  memory                  = 8192
  guest_id                = data.vsphere_virtual_machine.template[0].guest_id
  scsi_type               = data.vsphere_virtual_machine.template[0].scsi_type
  firmware                = data.vsphere_virtual_machine.template[0].firmware
  
  network_interface {
    network_id = data.vsphere_network.network[0].id
  }
  
  disk {
    label            = "disk0"
    size             = 512
    eagerly_scrub    = false
    thin_provisioned = true
  }
  
  clone {
    template_uuid = data.vsphere_virtual_machine.template[0].id
    
    customize {
      linux_options {
        host_name = "${local.name_prefix}-validator-${count.index + 1}"
        domain    = try(local.env.identity.domain, "local")
      }
      
      network_interface {
        ipv4_address = cidrhost(try(local.env.infrastructure.networking.subnet_cidr, "192.168.1.0/24"), count.index + 20)
        ipv4_netmask = 24
      }
      
      ipv4_gateway    = try(local.env.infrastructure.networking.gateway, "192.168.1.1")
      dns_server_list = ["8.8.8.8", "8.8.4.4"]
    }
  }
  
  tags = [for k, v in var.tags : "${k}=${v}"]
}

# RPC nodes
resource "vsphere_virtual_machine" "rpc" {
  count            = local.hci_platform == "vsphere" && try(local.node_pools.rpc.count, 0) > 0 ? local.node_pools.rpc.count : 0
  name             = "${local.name_prefix}-rpc-${count.index + 1}"
  resource_pool_id = data.vsphere_compute_cluster.cluster[0].resource_pool_id
  datastore_id     = data.vsphere_datastore.datastore[0].id
  
  num_cpus               = 4
  memory                  = 8192
  guest_id                = data.vsphere_virtual_machine.template[0].guest_id
  scsi_type               = data.vsphere_virtual_machine.template[0].scsi_type
  firmware                = data.vsphere_virtual_machine.template[0].firmware
  
  network_interface {
    network_id = data.vsphere_network.network[0].id
  }
  
  disk {
    label            = "disk0"
    size             = 256
    eagerly_scrub    = false
    thin_provisioned = true
  }
  
  clone {
    template_uuid = data.vsphere_virtual_machine.template[0].id
    
    customize {
      linux_options {
        host_name = "${local.name_prefix}-rpc-${count.index + 1}"
        domain    = try(local.env.identity.domain, "local")
      }
      
      network_interface {
        ipv4_address = cidrhost(try(local.env.infrastructure.networking.subnet_cidr, "192.168.1.0/24"), count.index + 30)
        ipv4_netmask = 24
      }
      
      ipv4_gateway    = try(local.env.infrastructure.networking.gateway, "192.168.1.1")
      dns_server_list = ["8.8.8.8", "8.8.4.4"]
    }
  }
  
  tags = [for k, v in var.tags : "${k}=${v}"]
}

# Note: Kubernetes cluster installation on these VMs would be done via:
# - Cloud-init scripts
# - Ansible playbooks
# - kubeadm
# - Rancher/K3s
# This is outside Terraform's scope but can be orchestrated via provisioners or external tools

