# Veris On-Prem Cluster Setup — GKE
#
# This Terraform module creates everything needed to register an existing
# GKE cluster with Veris for customer-hosted simulations:
#
#   1. veris namespace
#   2. ServiceAccount with RBAC for job management
#   3. Long-lived bearer token (Secret-bound)
#   4. Artifact Registry repository for agent images
#
# Usage:
#   terraform init
#   terraform apply
#   terraform output -json veris_cluster_registration
#
# Then register with Veris:
#   terraform output -raw veris_cluster_registration | \
#     curl -X POST https://api.veris.ai/v1/clusters \
#       -H "Authorization: Bearer $VERIS_API_KEY" \
#       -H "Content-Type: application/json" \
#       -d @-

terraform {
  required_version = ">= 1.5"
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = ">= 5.0"
    }
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = ">= 2.20"
    }
  }
}

# ---------------------------------------------------------------------------
# Variables
# ---------------------------------------------------------------------------

variable "project_id" {
  description = "GCP project ID"
  type        = string
}

variable "cluster_name" {
  description = "Name of the existing GKE cluster"
  type        = string
}

variable "region" {
  description = "GCP region or zone where the cluster is located"
  type        = string
}

variable "namespace" {
  description = "Kubernetes namespace for Veris jobs"
  type        = string
  default     = "veris"
}

variable "veris_organization_id" {
  description = "Your Veris organization ID (org_xxx)"
  type        = string
}

variable "ar_repository_name" {
  description = "Artifact Registry repository name for agent images"
  type        = string
  default     = "veris-simulation-images"
}

variable "ar_location" {
  description = "Artifact Registry location (e.g., us-central1)"
  type        = string
  default     = ""
}

variable "cluster_display_name" {
  description = "Display name for the cluster in Veris"
  type        = string
  default     = ""
}

# ---------------------------------------------------------------------------
# Data sources
# ---------------------------------------------------------------------------

provider "google" {
  project = var.project_id
}

data "google_container_cluster" "this" {
  name     = var.cluster_name
  location = var.region
  project  = var.project_id
}

data "google_client_config" "default" {}

provider "kubernetes" {
  host                   = "https://${data.google_container_cluster.this.endpoint}"
  token                  = data.google_client_config.default.access_token
  cluster_ca_certificate = base64decode(data.google_container_cluster.this.master_auth[0].cluster_ca_certificate)
}

# ---------------------------------------------------------------------------
# Namespace
# ---------------------------------------------------------------------------

resource "kubernetes_namespace_v1" "veris" {
  metadata {
    name = var.namespace
  }
}

# ---------------------------------------------------------------------------
# Service Account + RBAC
# ---------------------------------------------------------------------------

resource "kubernetes_service_account_v1" "veris" {
  metadata {
    name      = "veris-sa"
    namespace = kubernetes_namespace_v1.veris.metadata[0].name
  }
}

resource "kubernetes_role_v1" "veris_job_manager" {
  metadata {
    name      = "veris-job-manager"
    namespace = kubernetes_namespace_v1.veris.metadata[0].name
  }

  rule {
    api_groups = ["batch"]
    resources  = ["jobs"]
    verbs      = ["create", "get", "list", "delete", "watch"]
  }

  rule {
    api_groups = [""]
    resources  = ["pods", "pods/log"]
    verbs      = ["get", "list", "watch"]
  }

  rule {
    api_groups = [""]
    resources  = ["secrets", "configmaps"]
    verbs      = ["create", "get", "delete", "list"]
  }

  rule {
    api_groups = [""]
    resources  = ["namespaces"]
    verbs      = ["get"]
  }
}

resource "kubernetes_role_binding_v1" "veris" {
  metadata {
    name      = "veris-sa-binding"
    namespace = kubernetes_namespace_v1.veris.metadata[0].name
  }

  role_ref {
    api_group = "rbac.authorization.k8s.io"
    kind      = "Role"
    name      = kubernetes_role_v1.veris_job_manager.metadata[0].name
  }

  subject {
    kind      = "ServiceAccount"
    name      = kubernetes_service_account_v1.veris.metadata[0].name
    namespace = kubernetes_namespace_v1.veris.metadata[0].name
  }
}

# ---------------------------------------------------------------------------
# Long-lived bearer token (Secret-bound, does not expire)
# ---------------------------------------------------------------------------

resource "kubernetes_secret_v1" "veris_token" {
  metadata {
    name      = "veris-sa-token"
    namespace = kubernetes_namespace_v1.veris.metadata[0].name
    annotations = {
      "kubernetes.io/service-account.name" = kubernetes_service_account_v1.veris.metadata[0].name
    }
  }

  type                           = "kubernetes.io/service-account-token"
  wait_for_service_account_token = true
}

# ---------------------------------------------------------------------------
# Artifact Registry Repository
# ---------------------------------------------------------------------------

locals {
  # Strip zone suffix (e.g., us-central1-a → us-central1) for AR location
  ar_location = var.ar_location != "" ? var.ar_location : replace(var.region, "/-[a-z]$/", "")
}

resource "google_artifact_registry_repository" "veris" {
  location      = local.ar_location
  repository_id = var.ar_repository_name
  format        = "DOCKER"
  description   = "Veris simulation agent images"

  labels = {
    managed-by = "veris-terraform"
    purpose    = "veris-simulation-images"
  }
}

# ---------------------------------------------------------------------------
# Outputs — use these to register with Veris
# ---------------------------------------------------------------------------

locals {
  display_name = var.cluster_display_name != "" ? var.cluster_display_name : var.cluster_name
  ca_cert      = base64decode(data.google_container_cluster.this.master_auth[0].cluster_ca_certificate)
  token        = kubernetes_secret_v1.veris_token.data["token"]
  ar_url       = "${local.ar_location}-docker.pkg.dev/${var.project_id}/${var.ar_repository_name}"
}

output "veris_cluster_registration" {
  description = "JSON payload for POST /v1/clusters — register this cluster with Veris"
  sensitive   = true
  value = jsonencode({
    organization_id    = var.veris_organization_id
    name               = local.display_name
    provider           = "gke"
    api_server_url     = "https://${data.google_container_cluster.this.endpoint}"
    ca_certificate     = local.ca_cert
    namespace          = var.namespace
    auth_type          = "token"
    credentials        = { token = local.token }
    image_registry_url = local.ar_url
  })
}

output "cluster_endpoint" {
  description = "GKE API server endpoint"
  value       = "https://${data.google_container_cluster.this.endpoint}"
}

output "ar_repository_url" {
  description = "Artifact Registry URL for agent images"
  value       = local.ar_url
}

output "namespace" {
  description = "Kubernetes namespace for Veris jobs"
  value       = var.namespace
}

output "registration_command" {
  description = "Run this command to register the cluster with Veris"
  value       = "terraform output -raw veris_cluster_registration | curl -X POST https://api.veris.ai/v1/clusters -H 'Authorization: Bearer $VERIS_API_KEY' -H 'Content-Type: application/json' -d @-"
}
