/**
 * Copyright 2025 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

variable "bucket_config" {
  description = "Enable and configure auto-created bucket. Set fields to null to use defaults."
  type = object({
    force_destroy             = optional(bool)
    lifecycle_delete_age_days = optional(number)
    location                  = optional(string)
  })
  default = null
}

variable "bucket_name" {
  description = "Name of the bucket that will be used for the function code. It will be created with prefix prepended if bucket_config is not null."
  type        = string
  nullable    = false
}

variable "build_environment_variables" {
  description = "A set of key/value environment variable pairs available during build time."
  type        = map(string)
  default     = {}
}

variable "build_service_account" {
  description = "Build service account email."
  type        = string
  default     = null
}

variable "build_worker_pool" {
  description = "Build worker pool, in projects/<PROJECT-ID>/locations/<REGION>/workerPools/<POOL_NAME> format."
  type        = string
  default     = null
}

variable "bundle_config" {
  description = "Cloud function source. Path can point to a GCS object URI, or a local path. A local path to a zip archive will generate a GCS object using its basename, a folder will be zipped and the GCS object name inferred when not specified."
  type = object({
    path = string
    folder_options = optional(object({
      archive_path = optional(string)
      excludes     = optional(list(string))
    }), {})
  })
  nullable = false
  validation {
    condition = (
      var.bundle_config.path != null && (
        # GCS object
        (
          startswith(var.bundle_config.path, "gs://") &&
          endswith(var.bundle_config.path, ".zip")
        )
        ||
        # local folder
        length(fileset(pathexpand(var.bundle_config.path), "**/*")) > 0
        ||
        # local ZIP archive
        (
          try(fileexists(pathexpand(var.bundle_config.path)), null) != null &&
          endswith(var.bundle_config.path, ".zip")
        )
      )
    )
    error_message = "Bundle path must be set to a GCS object URI, a local folder or a local zip file."
  }
}

variable "context" {
  description = "Context-specific interpolations."
  type = object({
    condition_vars = optional(map(map(string)), {}) # not needed here?
    cidr_ranges    = optional(map(string), {})
    custom_roles   = optional(map(string), {})
    iam_principals = optional(map(string), {})
    kms_keys       = optional(map(string), {})
    locations      = optional(map(string), {})
    networks       = optional(map(string), {})
    project_ids    = optional(map(string), {})
    subnets        = optional(map(string), {})
    tag_values     = optional(map(string), {}) # not needed here?
  })
  nullable = false
  default  = {}
}

variable "description" {
  description = "Optional description."
  type        = string
  default     = "Terraform managed."
}

variable "direct_vpc_egress" {
  description = "Direct VPC egress configuration."
  type = object({
    mode       = string
    network    = string
    subnetwork = string
    tags       = optional(list(string))
  })
  default = null
  validation {
    condition = var.direct_vpc_egress == null || contains(
      ["VPC_EGRESS_ALL_TRAFFIC", "VPC_EGRESS_PRIVATE_RANGES_ONLY"],
      try(var.direct_vpc_egress.mode, "")
    )
    error_message = "Direct VPC egress mode must be one of VPC_EGRESS_ALL_TRAFFIC, VPC_EGRESS_PRIVATE_RANGES_ONLY."
  }
}

variable "docker_repository_id" {
  description = "User managed repository created in Artifact Registry."
  type        = string
  default     = null
}

variable "environment_variables" {
  description = "Cloud function environment variables."
  type        = map(string)
  default = {
    LOG_EXECUTION_ID = "true"
  }
}

variable "function_config" {
  description = "Cloud function configuration. Defaults to using main as entrypoint, 1 instance with 256MiB of memory, and 180 second timeout."
  type = object({
    automatic_update_policy          = optional(bool)
    binary_authorization_policy      = optional(string)
    cpu                              = optional(string, "0.166")
    entry_point                      = optional(string, "main")
    instance_count                   = optional(number, 1)
    max_instance_request_concurrency = optional(number)
    min_instance_count               = optional(number, 0)
    memory_mb                        = optional(number, 256) # Memory in MB
    on_deploy_update_policy          = optional(bool)
    runtime                          = optional(string, "python310")
    timeout_seconds                  = optional(number, 180)
  })
  default  = {}
  nullable = false
  validation {
    condition = !(
      coalesce(var.function_config.automatic_update_policy, false) &&
      coalesce(var.function_config.on_deploy_update_policy, false)
    )
    error_message = "Cannot set both automatic_update_policy and on_deploy_update_policy to true."
  }
}

variable "iam" {
  description = "IAM bindings for topic in {ROLE => [MEMBERS]} format."
  type        = map(list(string))
  default     = {}
}

variable "ingress_settings" {
  description = "Control traffic that reaches the cloud function. Allowed values are ALLOW_ALL, ALLOW_INTERNAL_AND_GCLB and ALLOW_INTERNAL_ONLY ."
  type        = string
  default     = null
}

variable "kms_key" {
  description = "Resource name of a KMS crypto key (managed by the user) used to encrypt/decrypt function resources in key id format. If specified, you must also provide an artifact registry repository using the docker_repository_id field that was created with the same KMS crypto key."
  type        = string
  default     = null
}

variable "labels" {
  description = "Resource labels."
  type        = map(string)
  default     = {}
}

variable "name" {
  description = "Name used for cloud function and associated resources."
  type        = string
}

variable "prefix" {
  description = "Optional prefix used for resource names."
  type        = string
  default     = null
  validation {
    condition     = var.prefix != ""
    error_message = "Prefix cannot be empty, please use null instead."
  }
}

variable "project_id" {
  description = "Project id used for all resources."
  type        = string
}

variable "region" {
  description = "Region used for all resources."
  type        = string
}

variable "secrets" {
  description = "Secret Manager secrets. Key is the variable name or mountpoint, volume versions are in version:path format."
  type = map(object({
    is_volume  = bool
    project_id = string
    secret     = string
    versions   = list(string)
  }))
  nullable = false
  default  = {}
}

variable "trigger_config" {
  description = "Function trigger configuration. Leave null for HTTP trigger."
  type = object({
    event_type   = string
    pubsub_topic = optional(string)
    region       = optional(string)
    event_filters = optional(list(object({
      attribute = string
      value     = string
      operator  = optional(string)
    })), [])
    service_account_email  = optional(string)
    service_account_create = optional(bool, false)
    retry_policy           = optional(string, "RETRY_POLICY_DO_NOT_RETRY") # default to avoid permadiff
  })
  default = null
}

variable "vpc_connector" {
  description = "VPC connector configuration. Set create to 'true' if a new connector needs to be created."
  type = object({
    name            = optional(string)
    egress_settings = optional(string)
  })
  nullable = false
  default  = {}
}
