terraform {
  required_version = ">= 1.0"

  required_providers {
    coder = {
      source  = "coder/coder"
      version = ">= 0.12"
    }
  }
}

variable "agent_id" {
  description = "The ID of a Coder agent."
  type        = string
}

variable "paths" {
  description = "List of files/directories to include in the archive. Defaults to the current directory."
  type        = list(string)
  default     = ["."]
}

variable "exclude_patterns" {
  description = "Exclude patterns for the archive."
  type        = list(string)
  default     = []
}

variable "compression" {
  description = "Compression algorithm for the archive. Supported: gzip, zstd, none."
  type        = string
  default     = "gzip"
  validation {
    condition     = contains(["gzip", "zstd", "none"], var.compression)
    error_message = "compression must be one of: gzip, zstd, none."
  }
}

variable "archive_name" {
  description = "Optional archive base name without extension. If empty, defaults to \"coder-archive\"."
  type        = string
  default     = "coder-archive"
}

variable "output_dir" {
  description = "Optional output directory where the archive will be written. Defaults to \"/tmp\"."
  type        = string
  default     = "/tmp"
}

variable "directory" {
  description = "Change current directory to this path before creating or extracting the archive. Defaults to the user's home directory."
  type        = string
  default     = "~"
}

variable "create_on_stop" {
  description = "If true, also create a run_on_stop script that creates the archive automatically on workspace stop."
  type        = bool
  default     = false
}

variable "extract_on_start" {
  description = "If true, the installer will wait for an archive and extract it on start."
  type        = bool
  default     = false
}

variable "extract_wait_timeout_seconds" {
  description = "Timeout (seconds) to wait for an archive when extract_on_start is true."
  type        = number
  default     = 5
}

# Provide a stable script filename and sensible defaults.
locals {
  extension = var.compression == "gzip" ? ".tar.gz" : var.compression == "zstd" ? ".tar.zst" : ".tar"

  # Ensure ~ is expanded because it cannot be expanded inside quotes in a
  # templated shell script.
  paths            = [for v in var.paths : replace(v, "/^~(\\/|$)/", "$$HOME$1")]
  exclude_patterns = [for v in var.exclude_patterns : replace(v, "/^~(\\/|$)/", "$$HOME$1")]
  directory        = replace(var.directory, "/^~(\\/|$)/", "$$HOME$1")
  output_dir       = replace(var.output_dir, "/^~(\\/|$)/", "$$HOME$1")

  archive_path = "${local.output_dir}/${var.archive_name}${local.extension}"
}

output "archive_path" {
  description = "Full path to the archive file that will be created, extracted, or both."
  value       = local.archive_path
}

# This script installs the user-facing archive script into $CODER_SCRIPT_BIN_DIR.
# The installed script can be run manually by the user to create an archive.
resource "coder_script" "archive_start_script" {
  agent_id           = var.agent_id
  display_name       = "Archive"
  icon               = "/icon/folder.svg"
  run_on_start       = true
  start_blocks_login = var.extract_on_start

  # Render the user-facing archive script with Terraform defaults, then write it to $CODER_SCRIPT_BIN_DIR
  script = templatefile("${path.module}/run.sh", {
    TF_LIB_B64              = base64encode(file("${path.module}/scripts/archive-lib.sh")),
    TF_PATHS                = join(" ", formatlist("%q", local.paths)),
    TF_EXCLUDE_PATTERNS     = join(" ", formatlist("%q", local.exclude_patterns)),
    TF_COMPRESSION          = var.compression,
    TF_ARCHIVE_PATH         = local.archive_path,
    TF_DIRECTORY            = local.directory,
    TF_EXTRACT_ON_START     = var.extract_on_start,
    TF_EXTRACT_WAIT_TIMEOUT = var.extract_wait_timeout_seconds,
  })
}

# Optionally, also register a run_on_stop script that creates the archive automatically
# when the workspace stops. It simply invokes the installed archive script.
resource "coder_script" "archive_stop_script" {
  count              = var.create_on_stop ? 1 : 0
  agent_id           = var.agent_id
  display_name       = "Archive"
  icon               = "/icon/folder.svg"
  run_on_stop        = true
  start_blocks_login = false

  # Call the installed script. It will log to stderr and print the archive path to stdout.
  # We redirect stdout to stderr to avoid surfacing the path in system logs if undesired.
  # Remove the redirection if you want the path to appear in stdout on stop as well.
  script = <<-EOT
    #!/usr/bin/env bash
    set -euo pipefail
    "$CODER_SCRIPT_BIN_DIR/coder-archive-create"
  EOT
}
