variable "wait_on" {
  type        = any
  description = "Resources to wait on"
  default     = true
}

variable "server_ip" {
  description = "Target server IP"
  type        = string
}

variable "ssh_private_key_path" {
  description = "Path to SSH private key"
  type        = string
  default     = "~/.ssh/id_rsa"
}

variable "app_name" {
  description = "Name of the application"
  type        = string
}

variable "image" {
  description = "Container image"
  type        = string
}

variable "ports" {
  description = "List of port mappings (e.g., ['8080:80', '8443:443'])"
  type        = list(string)
  default     = []
}

variable "volumes" {
  description = "List of volume mounts (e.g., ['/host/path:/container/path:Z'])"
  type        = list(string)
  default     = []
}

variable "environment" {
  description = "Environment variables as key-value pairs"
  type        = map(string)
  default     = {}
}

variable "command" {
  description = "Command to run in container (list of strings)"
  type        = list(string)
  default     = []
}

variable "haproxy_services" {
  description = "Multiple HAProxy service configurations"
  type = list(object({
    name   = string
    domain = string
    port   = string
    host   = optional(string, "127.0.0.1")
    tls    = optional(bool, false)
    grpc_port = optional(string, "")
  }))
  default = []
}

variable "depends_on_services" {
  description = "List of systemd services this app depends on"
  type        = list(string)
  default     = []
}

variable "restart_policy" {
  description = "Systemd restart policy"
  type        = string
  default     = "always"
}

variable "healthcmd" {
  default = ""
}

locals {
  # Build all HAProxy labels for multiple services
  haproxy_labels = flatten([
    for svc in var.haproxy_services : [
      "Label=haproxy.${svc.name}.enable=true",
      "Label=haproxy.${svc.name}.domain=${svc.domain}",
      "Label=haproxy.${svc.name}.port=${svc.port}",
      "Label=haproxy.${svc.name}.host=${svc.host}",
      "Label=haproxy.${svc.name}.tls=${svc.tls}",
      #"Label=haproxy.${svc.name}.grpc_port=${svc.grpc_port}"
    ]
  ])
}

resource "null_resource" "deploy_quadlet_app" {
  depends_on = [var.wait_on]
  triggers = {
    app_name            = var.app_name
    image               = var.image
    server_ip           = var.server_ip
    ports               = jsonencode(var.ports)
    volumes             = jsonencode(var.volumes)
    environment         = jsonencode(var.environment)
    command             = jsonencode(var.command)
    haproxy_services    = jsonencode(var.haproxy_services)
    depends_on_services = jsonencode(var.depends_on_services)
    ssh_private_key_path = var.ssh_private_key_path
    restart_policy      = var.restart_policy
  }

  provisioner "remote-exec" {
    inline = compact(flatten([
      [
        # Verify the user systemd session is ready and linger is enabled
        #"timeout 60 bash -c 'until loginctl show-user fourlights | grep -q \"Linger=yes\"; do sleep 2; done'",
        
        # Create base quadlet file
        "cat > /tmp/${var.app_name}.container << 'EOF'",
        "[Unit]",
        "Description=${var.app_name} Service",
        "After=network-online.target",
        "",
        "[Container]",
        "Image=${var.image}",
        "AutoUpdate=registry",
        "Network=containers.network"
      ],

      # Add ports (only if not empty)
        length(var.ports) > 0 ? formatlist("PublishPort=127.0.0.1:%s", var.ports) : [],

      # Add volumes (only if not empty)
        length(var.volumes) > 0 ? formatlist("Volume=%s", var.volumes) : [],

      # Add environment variables (only if not empty)
        length(var.environment) > 0 ? formatlist("Environment=%s=%s", keys(var.environment), values(var.environment)) : [],

      # Add command (only if not empty)
        length(var.command) > 0 ? ["Exec=${join(" ", var.command)}"] : [],

      # Add pre-computed HAProxy labels (only if not empty)
        length(local.haproxy_labels) > 0 ? local.haproxy_labels : [],

      # Add health checks if not empty
        var.healthcmd != "" ? ["HealthCmd=${var.healthcmd}"] : [],

      [
        "",
        "[Service]",
        "Restart=${var.restart_policy}",
        "",
        "[Install]",
        "WantedBy=default.target",
        "EOF",

        # Create volume directory
        "mkdir -p /opt/storage/data/${var.app_name}",

        # Move and activate
        # Create directory more robustly
        "test -d ~/.config/containers/systemd || mkdir -p ~/.config/containers/systemd",
        "cp /tmp/${var.app_name}.container ~/.config/containers/systemd/${var.app_name}.container",
        "systemctl --user daemon-reload",
        "timeout 60 bash -c 'until systemctl --user list-unit-files | grep -q \"^${var.app_name}.service\"; do sleep 2; systemctl --user daemon-reload; done'",
        
        "systemctl --user start ${var.app_name}",
        "systemctl --user status ${var.app_name} --no-pager",
      ]
    ]))


    connection {
      type        = "ssh"
      host        = var.server_ip
      user        = "fourlights"
      agent       = true
      agent_identity  = var.ssh_private_key_path
    }
  }

  provisioner "remote-exec" {
    when = destroy
    inline = [
      # Stop and remove the service
      "systemctl --user stop ${self.triggers.app_name} || true",

      # Remove the .container file
      "rm -f ~/.config/containers/systemd/${self.triggers.app_name}.container",

      # Reload systemd to remove the generated service
      "systemctl --user daemon-reload",

      # Force remove any lingering containers
      "podman rm -f ${self.triggers.app_name} || true"
    ]
    connection {
      type        = "ssh"
      host        = self.triggers.server_ip
      user        = "fourlights"
      agent       = true
      agent_identity  = self.triggers.ssh_private_key_path
    }

  }
}

output "app_name" {
  value = var.app_name
}

output "service_status" {
  value = "${var.app_name} deployed"
}

output "app_urls" {
  value = [for svc in var.haproxy_services : format("%s://%s", (svc.tls == true ? "https" : "http"), svc.domain)]
}

output "installed" {
  value = true
  depends_on = [null_resource.deploy_quadlet_app]
}