resource "google_service_account" "services" {
  project      = var.gcp_project_id
  account_id   = "dit-${random_id.deployment.hex}"
  display_name = "${local.deployment_name} service identity"
  description  = "Terraform-managed identity; usedby=${local.deployment_name}"
}

resource "google_compute_disk" "data" {
  name    = "${local.deployment_name}-data"
  project = var.gcp_project_id
  zone    = local.gcp_zone
  type    = "pd-balanced"
  size    = var.data_disk_size_gib
  labels  = local.labels
}

locals {
  secrets_env = <<-EOT
    MYSQL_ROOT_PASSWORD=${local.mysql_root_password}
    MYSQL_USER=${var.mysql_user}
    MYSQL_PASSWORD=${local.mysql_password}
    KAFKA_SASL_USERNAME=${local.kafka_sasl_username}
    KAFKA_SASL_PASSWORD=${local.kafka_sasl_password}
    PULSAR_PROXY_TOKEN=${data.external.pulsar_proxy_token.result.token}
    PULSAR_ADMIN_TOKEN=${data.external.pulsar_admin_token.result.token}
    PULSAR_CLIENT_TOKEN=${data.external.pulsar_client_token.result.token}
    SCHEMA_REGISTRY_USERNAME=${local.schema_registry_username}
    SCHEMA_REGISTRY_PASSWORD=${local.schema_registry_password}
  EOT

  compose_yaml = templatefile("${path.module}/../../templates/compose.yaml.tftpl", {
    mysql_image                       = local.images.mysql
    kafka_image                       = local.images.kafka
    pulsar_image                      = local.images.pulsar
    kafka_proxy_image                 = local.images.kafka_proxy
    schema_registry_image             = local.images.schema_registry
    mysql_port                        = local.ports.mysql
    kafka_public_port                 = local.ports.kafka_public
    kafka_sasl_port                   = local.ports.kafka_sasl
    kafka_pl_public_port              = local.ports.kafka_pl_public
    kafka_pl_sasl_port                = local.ports.kafka_pl_sasl
    pulsar_binary_port                = local.ports.pulsar_binary
    pulsar_admin_http_port            = local.ports.pulsar_admin_http
    schema_registry_port              = local.ports.schema_registry
    public_ip                         = google_compute_address.public.address
    kafka_privatelink_advertised_host = local.kafka_privatelink_advertised_host
    kafka_cluster_id                  = local.kafka_cluster_id
    enable_pulsar                     = var.enable_pulsar
    enable_schema_registry            = var.enable_schema_registry
  })
  mysql_config = templatefile("${path.module}/../../templates/mysql.cnf.tftpl", {})
  mysql_init = templatefile("${path.module}/../../templates/mysql-init.sql.tftpl", {
    mysql_user = var.mysql_user
  })
  service_unit = templatefile("${path.module}/../../templates/date-integration.service.tftpl", {})
  seed_script = templatefile("${path.module}/../../templates/seed-services.sh.tftpl", {
    mysql_user             = var.mysql_user
    pulsar_binary_port     = local.ports.pulsar_binary
    pulsar_admin_http_port = local.ports.pulsar_admin_http
    schema_registry_port   = local.ports.schema_registry
    enable_pulsar          = var.enable_pulsar
    enable_schema_registry = var.enable_schema_registry
  })
  schema_registry_jaas  = <<-EOT
    SchemaRegistry-Props {
      org.eclipse.jetty.jaas.spi.PropertyFileLoginModule required
      file="/etc/schema-registry/schema-registry-users.properties";
    };
  EOT
  schema_registry_users = "${local.schema_registry_username}: MD5:${md5(local.schema_registry_password)},user\n"
  install_services = templatefile("${path.module}/../../templates/install-services.sh.tftpl", {
    compose_b64               = base64encode(local.compose_yaml)
    mysql_config_b64          = base64encode(local.mysql_config)
    mysql_init_b64            = base64encode(local.mysql_init)
    pulsar_secret_b64         = local.pulsar_token_secret
    secrets_env_b64           = base64encode(local.secrets_env)
    service_unit_b64          = base64encode(local.service_unit)
    seed_script_b64           = base64encode(local.seed_script)
    schema_registry_jaas_b64  = base64encode(local.schema_registry_jaas)
    schema_registry_users_b64 = base64encode(local.schema_registry_users)
    mysql_credentials_hash    = sha256("${local.mysql_root_password}:${local.mysql_password}")
    pulsar_credentials_hash   = sha256("${local.pulsar_token_secret}:stable-network-v1")
  })
  user_data = templatefile("${path.module}/../../templates/user-data-linux.sh.tftpl", {
    data_device_path     = "/dev/disk/by-id/google-date-integration-data"
    compose_version      = "v2.39.4"
    compose_sha256_amd64 = "7af95166a730b87e172d4fc9aefea8725d3c6c7327d59149267b452114ddb7d4"
    compose_sha256_arm64 = "49082844b87f03cdcd5f5bbef1ba8c9c897b7a2dfb80cea18d61ec8ca6117e0c"
    install_services_b64 = base64encode(local.install_services)
  })
}

resource "google_compute_instance" "this" {
  name         = "${local.deployment_name}-services"
  project      = var.gcp_project_id
  zone         = local.gcp_zone
  machine_type = var.machine_type
  labels       = local.labels
  tags         = [local.deployment_name]

  boot_disk {
    auto_delete = true
    initialize_params {
      image  = "projects/debian-cloud/global/images/family/debian-12"
      size   = var.root_disk_size_gib
      type   = "pd-balanced"
      labels = local.labels
    }
  }

  attached_disk {
    source      = google_compute_disk.data.id
    device_name = "date-integration-data"
    mode        = "READ_WRITE"
  }

  network_interface {
    subnetwork = google_compute_subnetwork.services.id
    access_config {
      nat_ip = google_compute_address.public.address
    }
  }

  metadata = {
    block-project-ssh-keys = "true"
    enable-oslogin         = "true"
  }
  metadata_startup_script = local.user_data

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

  shielded_instance_config {
    enable_secure_boot          = true
    enable_vtpm                 = true
    enable_integrity_monitoring = true
  }

  lifecycle {
    precondition {
      condition     = data.google_project.current.project_id == var.gcp_project_id
      error_message = "The active Google provider project does not match gcp_project_id."
    }
  }

  depends_on = [google_project_service.compute]
}

resource "terraform_data" "wait_for_initial_bootstrap" {
  triggers_replace = [google_compute_instance.this.id]

  provisioner "local-exec" {
    command     = "${path.module}/../../scripts/wait-for-gcp-bootstrap.sh"
    interpreter = ["/usr/bin/env", "bash", "-c"]
    environment = {
      GCP_PROJECT_ID    = var.gcp_project_id
      GCP_ZONE          = local.gcp_zone
      INSTANCE_NAME     = google_compute_instance.this.name
      BOOTSTRAP_TIMEOUT = "1800"
    }
  }
}

resource "terraform_data" "instance_state" {
  triggers_replace = [var.desired_state, google_compute_instance.this.id]

  provisioner "local-exec" {
    command = (
      var.desired_state == "running"
      ? "gcloud compute instances start '${google_compute_instance.this.name}' --project '${var.gcp_project_id}' --zone '${local.gcp_zone}' --quiet"
      : "gcloud compute instances stop '${google_compute_instance.this.name}' --project '${var.gcp_project_id}' --zone '${local.gcp_zone}' --quiet"
    )
    interpreter = ["/usr/bin/env", "bash", "-c"]
  }

  depends_on = [terraform_data.wait_for_initial_bootstrap]
}

resource "terraform_data" "wait_after_state_change" {
  triggers_replace = [var.desired_state, google_compute_instance.this.id]

  provisioner "local-exec" {
    command     = var.desired_state == "running" ? "${path.module}/../../scripts/wait-for-gcp-bootstrap.sh" : "true"
    interpreter = ["/usr/bin/env", "bash", "-c"]
    environment = {
      GCP_PROJECT_ID    = var.gcp_project_id
      GCP_ZONE          = local.gcp_zone
      INSTANCE_NAME     = google_compute_instance.this.name
      BOOTSTRAP_TIMEOUT = "1800"
    }
  }

  depends_on = [terraform_data.instance_state]
}
