
// Terraform configuration
terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 6.0"
    }
    tls = {
      source  = "hashicorp/tls"
      version = "~> 4.0"
    }
    random = {
      source  = "hashicorp/random"
      version = "~> 3.0"
    }
  }
}

// Configure the Google Cloud provider
provider "google" {
  project = var.project_id
  region  = var.region
  zone    = var.zone
}

locals {
  common_labels = merge(var.lemc_resource_labels, {
    lemc_uuid     = var.lemc_uuid
    lemc_scope    = var.lemc_scope
    lemc_username = var.lemc_username
    lemc_user_id  = var.lemc_user_id
    lemc_recipe   = var.lemc_recipe_name
    lemc_page_id  = var.lemc_page_id
  })

  instance_tags = distinct(concat(["${var.resource_prefix}-vm"], var.lemc_resource_tags))
}

// Generate SSH key pair for Linux
resource "tls_private_key" "ssh" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

// Generate a strong random password for Windows Administrator
resource "random_password" "admin_password" {
  count            = var.is_windows ? 1 : 0
  length           = 16
  special          = true
  upper            = true
  lower            = true
  numeric          = true
  override_special = "!@#$%^&*()-_+=" # use a safe set of special characters (no quotes or slashes)
}

// Data source to get the latest Windows Server image
data "google_compute_image" "windows_image" {
  count   = var.is_windows ? 1 : 0
  family  = "windows-2022"
  project = "windows-cloud"
}

// VPC network
resource "google_compute_network" "vpc" {
  name                    = "${var.resource_prefix}-vpc"
  auto_create_subnetworks = false
}

// Subnetwork
resource "google_compute_subnetwork" "subnet" {
  name          = "${var.resource_prefix}-subnet"
  ip_cidr_range = "10.0.0.0/24"
  region        = var.region
  network       = google_compute_network.vpc.id
}

// Linux SSH firewall rule
resource "google_compute_firewall" "allow_linux_ssh" {
  count   = var.is_windows ? 0 : 1
  name    = "${var.resource_prefix}-allow-ssh-${var.ssh_port}"
  network = google_compute_network.vpc.name

  allow {
    protocol = "tcp"
    ports    = [tostring(var.ssh_port)]
  }

  source_ranges = ["0.0.0.0/0"]
  target_tags   = ["${var.resource_prefix}-vm"]
}

// Windows RDP firewall rule
resource "google_compute_firewall" "allow_windows_rdp" {
  count   = var.is_windows ? 1 : 0
  name    = "${var.resource_prefix}-allow-rdp"
  network = google_compute_network.vpc.name

  allow {
    protocol = "tcp"
    ports    = ["3389"]
  }

  source_ranges = ["0.0.0.0/0"]
  target_tags   = ["${var.resource_prefix}-vm"]
}

# Explicit egress allow rule for instances (covers both Windows and Linux)
resource "google_compute_firewall" "allow_egress_all" {
  name      = "${var.resource_prefix}-allow-egress-all"
  network   = google_compute_network.vpc.name
  direction = "EGRESS"

  allow {
    protocol = "all"
  }

  destination_ranges = ["0.0.0.0/0"]
  target_tags        = ["${var.resource_prefix}-vm"]
}

// Compute instance
resource "google_compute_instance" "vm" {
  name                      = var.resource_prefix
  machine_type              = var.machine_type
  min_cpu_platform          = var.enable_nested_virtualization && var.min_cpu_platform != "" ? var.min_cpu_platform : null
  allow_stopping_for_update = true
  tags                      = local.instance_tags

  advanced_machine_features {
    enable_nested_virtualization = var.enable_nested_virtualization
  }

  boot_disk {
    initialize_params {
      # Prefer explicit image if provided; otherwise, for Windows fall back to the latest family image
      image = var.image != "" ? var.image : (var.is_windows ? data.google_compute_image.windows_image[0].self_link : null)
      size  = var.disk_size
    }
  }

  network_interface {
    subnetwork = google_compute_subnetwork.subnet.name

    access_config {
      // Ephemeral public IP
    }
  }

  metadata = merge(
    var.is_windows ? {
      # Windows startup script to set Administrator password
      "windows-startup-script-ps1" = <<-EOS
        # PowerShell startup script to set the built-in Administrator (RID 500) password
        $ErrorActionPreference = 'Stop'
        try {
          # Try to detect the built-in Administrator by RID 500; fallback to provided variable
          $admin = Get-LocalUser | Where-Object { $_.SID.Value -match '-500$' }
          if ($null -eq $admin) {
            $admin = Get-LocalUser -Name "${var.windows_admin_username}" -ErrorAction SilentlyContinue
          }
          if ($null -ne $admin) {
            $name = $admin.Name
          } else {
            $name = "${var.windows_admin_username}"
          }
          net user $name "${random_password.admin_password[0].result}" /active:yes
        } catch {
          Write-Host "Failed to set password for admin account: $_"
        }
        # Enable RDP if not already enabled
        Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -name "fDenyTSConnections" -value 0
        Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
      EOS
      "enable-windows-ssh"         = "TRUE"
      } : {
      "ssh-keys" = "user:${tls_private_key.ssh.public_key_openssh}"
      "startup-script" = templatefile("/lemc/private/configure.sh", {
        ssh_port = var.ssh_port
      })
    }
  )

  labels = local.common_labels
}
