#!/usr/bin/env bash
# dockerize_app — Empaqueta una app del registry para deploy a VPS organic-machine
#                  via Docker + Traefik + Coolify. Genera Dockerfile, docker-compose.yml,
#                  traefik-dynamic.yml, sube via rsync y arranca el stack remoto.
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REGISTRY_ROOT="$(cd "$SCRIPT_DIR/../../../" && pwd)"

source "$SCRIPT_DIR/../infra/rsync_deploy.sh"

# ---------------------------------------------------------------------------
# _dockerize_app_usage — imprime ayuda y sale con error
# ---------------------------------------------------------------------------
_dockerize_app_usage() {
    cat >&2 <<'USAGE'
Uso: dockerize_app <app_name> [opciones]

  --domain DOMAIN           Dominio público (ej: kanban.organic-machine.com)
  --port PORT               Puerto interno del contenedor (default: 8080)
  --ssh-host HOST           Host SSH destino (default: organic-machine.com)
  --remote-dir DIR          Directorio remoto (default: /home/ubuntu/coolify-apps/<app>)
  --basic-auth USER:PASS    Credenciales basicAuth para Traefik
  --no-auth                 Deshabilitar basicAuth (por defecto: auth ON)
  --no-gzip                 Deshabilitar gzip middleware
  --env KEY=VAL             Variable de entorno (repetible)
  --volume NAME             Volume Docker (se monta en /data)
  --build-cmd CMD           Comando de build personalizado
  --standalone              Crear repo Gitea + git clone remoto en vez de rsync
  --dry-run                 Mostrar artefactos generados sin ejecutar nada
USAGE
    return 1
}

# ---------------------------------------------------------------------------
# _dockerize_app_generate_dockerfile — genera Dockerfile multi-stage para Go
# ---------------------------------------------------------------------------
_dockerize_app_generate_dockerfile() {
    local binary_name="$1"
    local port="$2"
    shift 2
    local env_vars=("$@")

    cat <<DOCKERFILE
# Stage build
FROM golang:1.23-alpine AS builder

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o ${binary_name} .

# Stage final
FROM alpine:latest

RUN apk --no-cache add ca-certificates tzdata

WORKDIR /app

COPY --from=builder /app/${binary_name} .

DOCKERFILE

    if [[ ${#env_vars[@]} -gt 0 ]]; then
        for kv in "${env_vars[@]}"; do
            [[ -n "$kv" ]] && echo "ENV ${kv%%=*}=${kv#*=}"
        done
        echo ""
    fi

    cat <<DOCKERFILE
EXPOSE ${port}

ENTRYPOINT ["./${binary_name}"]
DOCKERFILE
}

# ---------------------------------------------------------------------------
# _dockerize_app_generate_compose — genera docker-compose.yml
# ---------------------------------------------------------------------------
_dockerize_app_generate_compose() {
    local project_name="$1"
    local service_name="$2"
    local build_context="$3"
    local dockerfile_path="$4"
    local port="$5"
    local volume_name="$6"
    local network="$7"
    shift 7
    local env_vars=("$@")

    cat <<COMPOSE
name: ${project_name}

services:
  ${service_name}:
    build:
      context: ${build_context}
      dockerfile: ${dockerfile_path}
    container_name: ${service_name}
    restart: unless-stopped
    ports:
      - "${port}:${port}"
COMPOSE

    if [[ -n "$volume_name" ]]; then
        cat <<COMPOSE
    volumes:
      - ${volume_name}:/data
COMPOSE
    fi

    if [[ ${#env_vars[@]} -gt 0 ]]; then
        echo "    environment:"
        for kv in "${env_vars[@]}"; do
            local key="${kv%%=*}"
            echo "      - ${key}=\${${key}:-}"
        done
    fi

    cat <<COMPOSE
    networks:
      - ${network}
COMPOSE

    if [[ -n "$volume_name" ]]; then
        cat <<COMPOSE

volumes:
  ${volume_name}:
COMPOSE
    fi

    cat <<COMPOSE

networks:
  ${network}:
    external: true
COMPOSE
}

# ---------------------------------------------------------------------------
# _dockerize_app_generate_traefik_dynamic — genera traefik-dynamic.yml
# ---------------------------------------------------------------------------
_dockerize_app_generate_traefik_dynamic() {
    local name="$1"
    local domain="$2"
    local upstream_url="$3"
    local basic_auth_line="$4"   # "" para deshabilitar
    local enable_gzip="$5"       # "true" | "false"

    # Construir lista de middlewares HTTPS
    local https_middlewares=()
    if [[ -n "$basic_auth_line" ]]; then
        https_middlewares+=("${name}-auth")
    fi
    if [[ "$enable_gzip" == "true" ]]; then
        https_middlewares+=("${name}-gzip")
    fi

    cat <<TRAEFIK
http:
  routers:
    ${name}-http:
      rule: "Host(\`${domain}\`)"
      entryPoints:
        - "http"
      middlewares:
        - "${name}-redirect"
      service: "${name}-service"

    ${name}-https:
      rule: "Host(\`${domain}\`)"
      entryPoints:
        - "https"
TRAEFIK

    if [[ ${#https_middlewares[@]} -gt 0 ]]; then
        echo "      middlewares:"
        for mw in "${https_middlewares[@]}"; do
            echo "        - \"${mw}\""
        done
    fi

    cat <<TRAEFIK
      service: "${name}-service"
      tls:
        certResolver: letsencrypt

  services:
    ${name}-service:
      loadBalancer:
        servers:
          - url: "${upstream_url}"

  middlewares:
    ${name}-redirect:
      redirectScheme:
        scheme: "https"
TRAEFIK

    if [[ -n "$basic_auth_line" ]]; then
        cat <<TRAEFIK
    ${name}-auth:
      basicAuth:
        users:
          - "${basic_auth_line}"
TRAEFIK
    fi

    if [[ "$enable_gzip" == "true" ]]; then
        cat <<TRAEFIK
    ${name}-gzip:
      compress: true
TRAEFIK
    fi
}

# ---------------------------------------------------------------------------
# _dockerize_app_merge_env_file — merge no destructivo de .env
# Agrega solo keys que no existen ya. Avisa de conflictos.
# ---------------------------------------------------------------------------
_dockerize_app_merge_env_file() {
    local env_file="$1"
    shift
    local new_vars=("$@")

    for kv in "${new_vars[@]}"; do
        local key="${kv%%=*}"
        local val="${kv#*=}"
        if grep -q "^${key}=" "$env_file" 2>/dev/null; then
            echo "    WARNING: .env ya contiene '${key}', no se sobreescribe." >&2
        else
            echo "${key}=${val}" >> "$env_file"
        fi
    done
}

# ---------------------------------------------------------------------------
# dockerize_app — punto de entrada principal
# ---------------------------------------------------------------------------
dockerize_app() {
    local app_name="${1:-}"
    if [[ -z "$app_name" ]]; then
        _dockerize_app_usage
    fi
    shift

    # Defaults
    local domain=""
    local port=8080
    local ssh_host="organic-machine.com"
    local remote_dir=""
    local basic_auth=""
    local no_auth=false
    local no_gzip=false
    local env_vars=()
    local volume_name=""
    local build_cmd=""
    local standalone=false
    local dry_run=false

    # Parse args
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --domain)      domain="$2";        shift 2 ;;
            --port)        port="$2";           shift 2 ;;
            --ssh-host)    ssh_host="$2";       shift 2 ;;
            --remote-dir)  remote_dir="$2";     shift 2 ;;
            --basic-auth)  basic_auth="$2";     shift 2 ;;
            --no-auth)     no_auth=true;        shift ;;
            --no-gzip)     no_gzip=true;        shift ;;
            --env)         env_vars+=("$2");    shift 2 ;;
            --volume)      volume_name="$2";    shift 2 ;;
            --build-cmd)   build_cmd="$2";      shift 2 ;;
            --standalone)  standalone=true;     shift ;;
            --dry-run)     dry_run=true;        shift ;;
            *) echo "dockerize_app: opcion desconocida '$1'" >&2; _dockerize_app_usage ;;
        esac
    done

    # Validar que el dominio fue dado
    if [[ -z "$domain" ]]; then
        echo "dockerize_app: --domain es obligatorio" >&2
        return 1
    fi

    # Auth logic
    local auth_enabled=false
    if [[ "$no_auth" == "false" ]]; then
        auth_enabled=true
        if [[ -z "$basic_auth" ]]; then
            echo "dockerize_app: --basic-auth USER:PASS es obligatorio cuando auth esta ON. Usa --no-auth para deshabilitarlo." >&2
            return 1
        fi
    fi

    local enable_gzip="true"
    if [[ "$no_gzip" == "true" ]]; then
        enable_gzip="false"
    fi

    local start_ts
    start_ts=$(date +%s)

    echo "==> [1/13] Validando app '${app_name}' en registry.db..." >&2

    # Buscar registry.db
    local registry_db="${FN_REGISTRY_ROOT:-$REGISTRY_ROOT}/registry.db"
    if [[ ! -f "$registry_db" ]]; then
        echo "dockerize_app: registry.db no encontrado en '$registry_db'" >&2
        return 1
    fi

    # Consultar la app en la BD
    local app_row
    app_row=$(sqlite3 "$registry_db" \
        "SELECT dir_path || '|' || lang || '|' || name FROM apps WHERE id LIKE '${app_name}%' OR name = '${app_name}' LIMIT 1;" 2>/dev/null || true)
    if [[ -z "$app_row" ]]; then
        echo "dockerize_app: app '${app_name}' no encontrada en registry.db" >&2
        echo "  Consulta apps disponibles: sqlite3 '$registry_db' \"SELECT id, name, lang FROM apps ORDER BY name;\"" >&2
        return 1
    fi

    local app_dir_rel="${app_row%%|*}"
    local rest="${app_row#*|}"
    local app_lang="${rest%%|*}"
    local app_real_name="${rest#*|}"

    local app_dir="${REGISTRY_ROOT}/${app_dir_rel}"

    echo "    OK: '${app_real_name}' (lang=${app_lang}) en '${app_dir_rel}'" >&2

    # Fase 1: solo Go
    if [[ "$app_lang" != "go" ]]; then
        echo "dockerize_app: Phase 1 soporta solo apps Go. Lang detectado: '${app_lang}'" >&2
        return 1
    fi

    if [[ ! -d "$app_dir" ]]; then
        echo "dockerize_app: directorio de la app no encontrado: '$app_dir'" >&2
        return 1
    fi

    # Default remote_dir
    if [[ -z "$remote_dir" ]]; then
        remote_dir="/home/ubuntu/coolify-apps/${app_real_name}"
    fi

    echo "==> [2/13] Validando conectividad SSH a '${ssh_host}'..." >&2
    if [[ "$dry_run" == "false" ]]; then
        if ! ssh -o BatchMode=yes -o ConnectTimeout=5 "$ssh_host" true 2>/dev/null; then
            echo "dockerize_app: no se puede conectar a '${ssh_host}' via SSH" >&2
            return 1
        fi
        echo "    OK: SSH conectado." >&2
    else
        echo "    [dry-run] Saltando verificacion SSH." >&2
    fi

    # Generar bcrypt si auth ON
    local basic_auth_line=""
    local basic_auth_user=""
    if [[ "$auth_enabled" == "true" ]]; then
        echo "==> [3/13] Generando hash bcrypt para basicAuth..." >&2
        basic_auth_user="${basic_auth%%:*}"
        local basic_auth_pass="${basic_auth#*:}"
        if [[ -z "$basic_auth_user" || -z "$basic_auth_pass" ]]; then
            echo "dockerize_app: --basic-auth debe tener formato USER:PASS" >&2
            return 1
        fi
        if command -v htpasswd &>/dev/null; then
            basic_auth_line=$(htpasswd -nbB "$basic_auth_user" "$basic_auth_pass" 2>/dev/null)
        elif command -v python3 &>/dev/null; then
            # Fallback: bcrypt via python3 si está disponible
            basic_auth_line=$(python3 -c "
import bcrypt, sys
user, pw = sys.argv[1], sys.argv[2]
h = bcrypt.hashpw(pw.encode(), bcrypt.gensalt())
print(f'{user}:{h.decode()}')
" "$basic_auth_user" "$basic_auth_pass" 2>/dev/null) || {
                echo "dockerize_app: ni htpasswd ni python3+bcrypt disponibles para generar hash" >&2
                return 1
            }
        else
            echo "dockerize_app: 'htpasswd' no encontrado. Instalar con: sudo apt install apache2-utils" >&2
            return 1
        fi
        if [[ -z "$basic_auth_line" ]]; then
            echo "dockerize_app: no se pudo generar hash bcrypt" >&2
            return 1
        fi
        echo "    OK: hash generado para usuario '${basic_auth_user}'." >&2
    else
        echo "==> [3/13] BasicAuth deshabilitado (--no-auth)." >&2
    fi

    # -----------------------------------------------------------------------
    # Generar Dockerfile
    # -----------------------------------------------------------------------
    echo "==> [4/13] Generando Dockerfile..." >&2
    local dockerfile_path="${app_dir}/Dockerfile"
    local dockerfile_content
    if [[ ${#env_vars[@]} -gt 0 ]]; then
        dockerfile_content=$(_dockerize_app_generate_dockerfile \
            "$app_real_name" \
            "$port" \
            "${env_vars[@]}" 2>/dev/null || true)
    else
        dockerfile_content=$(_dockerize_app_generate_dockerfile \
            "$app_real_name" \
            "$port" 2>/dev/null || true)
    fi

    if [[ "$dry_run" == "true" ]]; then
        echo "--- Dockerfile (${dockerfile_path}) ---" >&2
        echo "$dockerfile_content" >&2
        echo "---" >&2
    elif [[ -f "$dockerfile_path" ]]; then
        echo "    INFO: Dockerfile ya existe en '${dockerfile_path}', no se sobreescribe." >&2
    else
        echo "$dockerfile_content" > "$dockerfile_path"
        echo "    OK: Dockerfile generado en '${dockerfile_path}'." >&2
    fi

    # -----------------------------------------------------------------------
    # Generar docker-compose.yml
    # -----------------------------------------------------------------------
    echo "==> [5/13] Generando docker-compose.yml..." >&2
    local compose_path="${app_dir}/docker-compose.yml"

    # Build context relativo al remote_dir (contexto remoto)
    # Localmente el compose vive en apps/<app>/, el contexto del build Docker
    # apunta al root del repo (../../) para que el Dockerfile pueda hacer COPY . .
    local build_context="../../"
    local dockerfile_in_compose="${app_dir_rel}/Dockerfile"

    local compose_content
    if [[ ${#env_vars[@]} -gt 0 ]]; then
        compose_content=$(_dockerize_app_generate_compose \
            "$app_real_name" \
            "$app_real_name" \
            "$build_context" \
            "$dockerfile_in_compose" \
            "$port" \
            "$volume_name" \
            "coolify" \
            "${env_vars[@]}" 2>/dev/null || true)
    else
        compose_content=$(_dockerize_app_generate_compose \
            "$app_real_name" \
            "$app_real_name" \
            "$build_context" \
            "$dockerfile_in_compose" \
            "$port" \
            "$volume_name" \
            "coolify" 2>/dev/null || true)
    fi

    if [[ "$dry_run" == "true" ]]; then
        echo "--- docker-compose.yml (${compose_path}) ---" >&2
        echo "$compose_content" >&2
        echo "---" >&2
    else
        echo "$compose_content" > "$compose_path"
        echo "    OK: docker-compose.yml generado en '${compose_path}'." >&2
    fi

    # -----------------------------------------------------------------------
    # Generar traefik-dynamic.yml
    # -----------------------------------------------------------------------
    echo "==> [6/13] Generando traefik-dynamic.yml..." >&2
    local traefik_path="${app_dir}/traefik-dynamic.yml"
    local upstream_url="http://${app_real_name}:${port}"
    # Nombre del router Traefik: reemplazar _ por - para nombres válidos
    local traefik_name="${app_real_name//_/-}"

    local traefik_content
    traefik_content=$(_dockerize_app_generate_traefik_dynamic \
        "$traefik_name" \
        "$domain" \
        "$upstream_url" \
        "$basic_auth_line" \
        "$enable_gzip" 2>/dev/null || true)

    if [[ "$dry_run" == "true" ]]; then
        echo "--- traefik-dynamic.yml (${traefik_path}) ---" >&2
        echo "$traefik_content" >&2
        echo "---" >&2
    else
        echo "$traefik_content" > "$traefik_path"
        echo "    OK: traefik-dynamic.yml generado en '${traefik_path}'." >&2
    fi

    # -----------------------------------------------------------------------
    # Generar .env
    # -----------------------------------------------------------------------
    local env_path="${app_dir}/.env"
    if [[ ${#env_vars[@]} -gt 0 ]]; then
        echo "==> [7/13] Generando/actualizando .env..." >&2
        if [[ "$dry_run" == "true" ]]; then
            echo "--- .env (${env_path}) ---" >&2
            for kv in "${env_vars[@]}"; do echo "$kv"; done >&2
            echo "---" >&2
        elif [[ -f "$env_path" ]]; then
            echo "    INFO: .env ya existe, aplicando merge no destructivo." >&2
            _dockerize_app_merge_env_file "$env_path" "${env_vars[@]}"
        else
            for kv in "${env_vars[@]}"; do echo "$kv"; done > "$env_path"
            echo "    OK: .env creado en '${env_path}'." >&2
        fi
    else
        echo "==> [7/13] Sin vars --env, omitiendo .env." >&2
    fi

    if [[ "$dry_run" == "true" ]]; then
        local end_ts
        end_ts=$(date +%s)
        local duration=$(( end_ts - start_ts ))
        echo "" >&2
        echo "[dry-run] Artefactos generados. Sin cambios remotos." >&2
        printf '{"status":"dry-run","app":"%s","domain":"%s","remote_dir":"%s","port":%d,"auth_enabled":%s,"gzip_enabled":%s,"duration_seconds":%d,"url":"https://%s"}\n' \
            "$app_real_name" "$domain" "$remote_dir" "$port" \
            "$auth_enabled" "$enable_gzip" "$duration" "$domain"
        return 0
    fi

    # -----------------------------------------------------------------------
    # Standalone: crear repo Gitea + push
    # -----------------------------------------------------------------------
    if [[ "$standalone" == "true" ]]; then
        echo "==> [8/13] Creando repo Gitea (standalone mode)..." >&2
        source "$SCRIPT_DIR/../infra/gitea_create_repo.sh"
        source "$SCRIPT_DIR/../infra/gitea_push_directory.sh"
        gitea_create_repo "dataforge" "$app_real_name" "true" "App ${app_real_name} — dockerized via dockerize_app" >&2 || true
        gitea_push_directory "$app_dir" "dataforge" "$app_real_name" "master" >&2
        echo "    OK: repo Gitea 'dataforge/${app_real_name}' sincronizado." >&2

        echo "==> [9/13] Clonando/actualizando repo en remoto (standalone mode)..." >&2
        local gitea_base="${GITEA_URL:-https://git.organic-machine.com}"
        ssh "$ssh_host" bash <<REMOTE
set -euo pipefail
if [[ -d '${remote_dir}/.git' ]]; then
    echo "  git pull en '${remote_dir}'..."
    cd '${remote_dir}' && git pull origin master
else
    echo "  git clone en '${remote_dir}'..."
    mkdir -p '${remote_dir}'
    git clone '${gitea_base}/dataforge/${app_real_name}.git' '${remote_dir}'
fi
REMOTE
        echo "    OK: repo remoto actualizado." >&2
    else
        echo "==> [8/13] Rsync del app al VPS..." >&2
        # Sincronizar solo el directorio de la app (más liviano que el repo completo)
        # El build context remoto apunta a ../../ desde remote_dir, por lo que
        # también necesitamos los ficheros Go del root del repo.
        # Solución: rsync el root del registry al VPS en un dir de build, y además
        # sincronizar los artefactos Docker generados.
        local remote_build_root="/home/ubuntu/coolify-build/${app_real_name}"
        echo "    Sincronizando repo completo a '${ssh_host}:${remote_build_root}'..." >&2
        rsync_deploy "${REGISTRY_ROOT}/" "$ssh_host" "$remote_build_root" > /dev/null
        echo "    OK: repo sincronizado en '${remote_build_root}'." >&2

        echo "==> [9/13] Preparando directorio remoto de deploy..." >&2
        ssh "$ssh_host" "mkdir -p '${remote_dir}'"
        echo "    OK: '${remote_dir}' disponible." >&2
    fi

    # -----------------------------------------------------------------------
    # Subir traefik-dynamic.yml al proxy de Coolify
    # -----------------------------------------------------------------------
    echo "==> [10/13] Subiendo traefik-dynamic.yml a Coolify proxy..." >&2
    local traefik_coolify_path="/data/coolify/proxy/dynamic/${traefik_name}.yml"
    ssh "$ssh_host" "sudo mkdir -p /data/coolify/proxy/dynamic/" >&2
    echo "$traefik_content" | ssh "$ssh_host" \
        "sudo tee '${traefik_coolify_path}' > /dev/null"
    echo "    OK: traefik-dynamic.yml en '${traefik_coolify_path}'." >&2

    # -----------------------------------------------------------------------
    # Subir docker-compose.yml, Dockerfile y .env al remote_dir
    # -----------------------------------------------------------------------
    echo "==> [11/13] Subiendo artefactos Docker a '${ssh_host}:${remote_dir}'..." >&2
    if [[ "$standalone" == "true" ]]; then
        # En standalone, el repo ya está clonado en remote_dir
        echo "    [standalone] Artefactos ya en remote_dir via git." >&2
    else
        # Copiar los artefactos generados al remote_dir (que es el subdir de la app en el build root)
        local remote_app_subdir="${remote_build_root}/${app_dir_rel}"
        ssh "$ssh_host" "mkdir -p '${remote_app_subdir}'" >&2
        scp "$compose_path" "${ssh_host}:${remote_app_subdir}/docker-compose.yml" >&2
        scp "$dockerfile_path" "${ssh_host}:${remote_app_subdir}/Dockerfile" >&2
        if [[ -f "$env_path" ]]; then
            scp "$env_path" "${ssh_host}:${remote_app_subdir}/.env" >&2
        fi
        # Apuntar remote_dir al subdir donde está el compose
        remote_dir="$remote_app_subdir"
        echo "    OK: artefactos subidos a '${remote_app_subdir}'." >&2
    fi

    # -----------------------------------------------------------------------
    # Verificar red coolify + docker compose up --build
    # -----------------------------------------------------------------------
    echo "==> [12/13] Verificando red Docker 'coolify' y levantando stack..." >&2
    ssh "$ssh_host" bash <<REMOTE
set -euo pipefail
if ! docker network ls --format '{{.Name}}' | grep -q '^coolify$'; then
    echo "  Creando red Docker 'coolify'..."
    docker network create coolify
fi
echo "  Red 'coolify' disponible."
cd '${remote_dir}'
echo "  docker compose build + up..."
docker compose up -d --build
echo "  Stack levantado."
REMOTE
    echo "    OK: stack Docker activo." >&2

    # -----------------------------------------------------------------------
    # Health check
    # -----------------------------------------------------------------------
    echo "==> [13/13] Health check en 'https://${domain}'..." >&2
    local health_url="https://${domain}/"
    local attempts=0
    local max_attempts=10
    local http_code="000"
    while [[ $attempts -lt $max_attempts ]]; do
        if [[ -n "$basic_auth_user" ]]; then
            http_code=$(curl -sk -o /dev/null -w "%{http_code}" \
                -u "${basic_auth_user}:${basic_auth#*:}" \
                "$health_url" 2>/dev/null || echo "000")
        else
            http_code=$(curl -sk -o /dev/null -w "%{http_code}" \
                "$health_url" 2>/dev/null || echo "000")
        fi
        # 200 = OK, 401 = basicAuth activo (correcto), 301/302 = redirect (transitorio)
        if [[ "$http_code" == "200" || "$http_code" == "401" ]]; then
            break
        fi
        attempts=$(( attempts + 1 ))
        echo "    Intento ${attempts}/${max_attempts} — HTTP ${http_code}, esperando 3s..." >&2
        sleep 3
    done

    local end_ts
    end_ts=$(date +%s)
    local duration=$(( end_ts - start_ts ))

    # Obtener container_id
    local container_id=""
    container_id=$(ssh "$ssh_host" \
        "docker ps --filter name=${app_real_name} --format '{{.ID}}' | head -1" 2>/dev/null || true)

    if [[ "$http_code" == "200" || "$http_code" == "401" ]]; then
        echo "    OK: servicio respondiendo HTTP ${http_code}." >&2
        local status_val="ok"
    else
        echo "    ERROR: health check timeout tras ${max_attempts} intentos." >&2
        local status_val="failed"
    fi

    printf '{"status":"%s","app":"%s","domain":"%s","remote_dir":"%s","container_id":"%s","duration_seconds":%d,"auth_enabled":%s,"gzip_enabled":%s,"http_code":"%s","url":"https://%s"}\n' \
        "$status_val" \
        "$app_real_name" \
        "$domain" \
        "$remote_dir" \
        "$container_id" \
        "$duration" \
        "$auth_enabled" \
        "$enable_gzip" \
        "$http_code" \
        "$domain"

    [[ "$status_val" == "ok" ]]
}

# ---------------------------------------------------------------------------
# Punto de entrada directo (bash dockerize_app.sh <app> [flags])
# ---------------------------------------------------------------------------
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
    dockerize_app "$@"
fi
