# Google Cloud Marketplace — 1-Click MassEngine Cluster Terraform Module
# Supports both the 1-Core Free Tier ($0/mo, 1 vCPU, 1 node, up to 1M vectors)
# and Production Multi-Node HA Clusters metered hourly per vCPU via Google Cloud
# Marketplace ubbagent (--license-mode=gcp-marketplace).

terraform {
  required_version = ">= 1.5.0"
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = ">= 5.0.0"
    }
    random = {
      source  = "hashicorp/random"
      version = ">= 3.5.0"
    }
  }
}

variable "project_id" {
  type        = string
  description = "Google Cloud Project ID"
}

variable "region" {
  type        = string
  default     = "us-central1"
  description = "GCP Region for the MassEngine cluster"
}

variable "zone" {
  type        = string
  default     = "us-central1-a"
  description = "Primary GCP Zone"
}

variable "cluster_name" {
  type        = string
  default     = "massengine-cluster"
  description = "Cluster name prefix"
}

variable "deployment_tier" {
  type        = string
  default     = "Production-HA-Cluster"
  description = "Select '1-Core-Free-Single-Node' ($0/mo, 1 vCPU, 1M vectors) or 'Production-HA-Cluster' (metered per vCPU via Google Cloud Marketplace)"
  validation {
    condition     = contains(["1-Core-Free-Single-Node", "Production-HA-Cluster"], var.deployment_tier)
    error_message = "deployment_tier must be 1-Core-Free-Single-Node or Production-HA-Cluster."
  }
}

variable "node_count" {
  type        = number
  default     = 2
  description = "Number of cluster nodes (automatically forced to 1 when deployment_tier is 1-Core-Free-Single-Node)"
}

variable "machine_type" {
  type        = string
  default     = "c3d-standard-4"
  description = "GCE machine type. Each active vCPU includes 2 TB of NVMe storage allowance."
}

variable "local_nvme_ssd_partitions" {
  type        = number
  default     = 1
  description = "Number of 375 GB Local NVMe SSD partitions per node for nvme-mode storage (0 for Free Tier e2-small)"
}

variable "network" {
  type        = string
  default     = "default"
  description = "VPC network name"
}

variable "allowed_client_cidr" {
  type        = string
  default     = "10.0.0.0/8"
  description = "CIDR range allowed to reach the MassEngine HTTP/REST API on port 8080"
}

variable "license_key" {
  type        = string
  default     = ""
  sensitive   = true
  description = "Optional signed per-core license key (meli_...). Leave blank for Free Tier or automatic GCP Marketplace metering."
}

locals {
  is_free_tier        = var.deployment_tier == "1-Core-Free-Single-Node"
  effective_nodes     = local.is_free_tier ? 1 : var.node_count
  effective_max_cores = local.is_free_tier ? 1 : 0
  license_mode        = local.is_free_tier ? "free" : (var.license_key != "" ? "signed-key" : "gcp-marketplace")
}

resource "random_password" "cluster_hmac_secret" {
  length  = 48
  special = false
}

resource "google_service_account" "marketplace_metering" {
  project      = var.project_id
  account_id   = "${var.cluster_name}-sa"
  display_name = "MassEngine GCP Marketplace Per-Core Metering Service Account"
}

resource "google_project_iam_member" "service_control_report" {
  project = var.project_id
  role    = "roles/servicemanagement.serviceController"
  member  = "serviceAccount:${google_service_account.marketplace_metering.email}"
}

resource "google_compute_firewall" "massengine_internal_peers" {
  project = var.project_id
  name    = "${var.cluster_name}-internal-peers"
  network = var.network

  allow {
    protocol = "tcp"
    ports    = ["8080", "9410"]
  }

  source_tags = ["${var.cluster_name}-node"]
  target_tags = ["${var.cluster_name}-node"]
}

resource "google_compute_firewall" "massengine_client_api" {
  project = var.project_id
  name    = "${var.cluster_name}-client-api"
  network = var.network

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

  source_ranges = [var.allowed_client_cidr]
  target_tags   = ["${var.cluster_name}-node"]
}

resource "google_compute_instance" "node" {
  count        = local.effective_nodes
  project      = var.project_id
  name         = "${var.cluster_name}-node-${count.index}"
  machine_type = var.machine_type
  zone         = var.zone
  tags         = ["${var.cluster_name}-node"]

  boot_disk {
    initialize_params {
      image = "ubuntu-os-cloud/ubuntu-2404-lts-amd64"
      size  = 64
      type  = "pd-ssd"
    }
  }

  dynamic "scratch_disk" {
    for_each = range(local.is_free_tier ? 0 : var.local_nvme_ssd_partitions)
    content {
      interface = "NVME"
    }
  }

  network_interface {
    network = var.network
  }

  service_account {
    email  = google_service_account.marketplace_metering.email
    scopes = ["https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/servicecontrol"]
  }

  metadata = {
    massengine-license-mode = local.license_mode
    massengine-max-cores    = tostring(local.effective_max_cores)
    massengine-node-count   = tostring(local.effective_nodes)
    startup-script = <<-EOT
      #!/usr/bin/env bash
      set -euo pipefail
      export MASSENGINE_LICENSE_MODE="${local.license_mode}"
      export MASSENGINE_MAX_CORES="${local.effective_max_cores}"
      export MASSENGINE_NODE_COUNT="${local.effective_nodes}"
      export MASSENGINE_LICENSE_KEY="${var.license_key}"
      mkdir -p /var/lib/massengine
      if [[ -b /dev/nvme0n1 ]] && ! mountpoint -q /var/lib/massengine; then
        mkfs.ext4 -F /dev/nvme0n1 || true
        mount -o noatime /dev/nvme0n1 /var/lib/massengine || true
      fi
      if [[ -x /usr/local/bin/massengine-node ]]; then
        systemctl enable --now massengine-node
      fi
    EOT
  }
}

output "cluster_name" {
  value       = var.cluster_name
  description = "Deployed MassEngine cluster name"
}

output "license_mode" {
  value       = local.license_mode
  description = "Active MassEngine per-core license mode (free, gcp-marketplace, or signed-key)"
}

output "node_internal_ips" {
  value       = google_compute_instance.node[*].network_interface[0].network_ip
  description = "Internal VPC IP addresses of MassEngine cluster nodes"
}

output "cluster_hmac_secret" {
  value       = random_password.cluster_hmac_secret.result
  sensitive   = true
  description = "Auto-generated HMAC secret for cluster authentication"
}
