#!/usr/bin/env bash
set -euo pipefail

CONFIG=/etc/chart-debug.conf
MAX_LOG_LINES=4000

if [[ ! -r "$CONFIG" ]]; then
  echo "chart-debug is not configured" >&2
  exit 1
fi

# Root-owned configuration written by install-chart-debug.
# shellcheck source=/dev/null
source "$CONFIG"

original=${1:-${SSH_ORIGINAL_COMMAND:-}}
if [[ -z "$original" || "$original" == *$'\n'* || "$original" == *$'\r'* ]]; then
  echo "usage: logs --since 20m | status | container-state | recent-deploy | capture-read ID | capture-delete ID" >&2
  exit 2
fi
read -r -a args <<< "$original"

logger -t chart-debug -- "user=${SUDO_USER:-${USER:-unknown}} from=${SSH_CONNECTION:-local} command=$original"

resolve_container() {
  local id name
  local -a matches=()
  while read -r id name; do
    [[ -n "$id" && "$name" =~ $CHART_CONTAINER_PATTERN ]] && matches+=("$id")
  done < <(docker ps --format '{{.ID}} {{.Names}}')
  if [[ ${#matches[@]} -ne 1 ]]; then
    echo "container selector matched ${#matches[@]} running containers" >&2
    exit 3
  fi
  printf '%s' "${matches[0]}"
}

redact() {
  sed -E \
    -e 's/(Authorization:[[:space:]]*Bearer[[:space:]]+)[A-Za-z0-9._-]+/\1[REDACTED]/Ig' \
    -e 's/((token|secret|password|api[_-]?key)["=:[:space:]]+)[^,[:space:]"}]+/\1[REDACTED]/Ig' \
    -e 's/([?&](code|session|state)=)[^&[:space:]]+/\1[REDACTED]/Ig'
}

valid_capture_id() {
  [[ "$1" =~ ^c-[A-Za-z0-9_-]{12}$ ]]
}

case "${args[0]}" in
  logs)
    [[ ${#args[@]} -eq 3 && "${args[1]}" == "--since" ]] || {
      echo "usage: logs --since 20m" >&2; exit 2;
    }
    [[ "${args[2]}" =~ ^[1-9][0-9]*(s|m|h|d)$ ]] || {
      echo "invalid duration" >&2; exit 2;
    }
    container=$(resolve_container)
    docker logs --timestamps --tail "$MAX_LOG_LINES" --since "${args[2]}" "$container" 2>&1 | redact
    ;;
  status)
    [[ ${#args[@]} -eq 1 ]] || { echo "usage: status" >&2; exit 2; }
    container=$(resolve_container)
    token=""
    while IFS= read -r entry; do
      [[ "$entry" == CHART_AUTH_TOKEN=* ]] && token=${entry#CHART_AUTH_TOKEN=}
    done < <(docker inspect --format '{{range .Config.Env}}{{println .}}{{end}}' "$container")
    if [[ -n "$token" ]]; then
      [[ "$token" != *$'\n'* && "$token" != *$'\r'* ]] || {
        echo "invalid CHART_AUTH_TOKEN" >&2; exit 4;
      }
      escaped_token=${token//\\/\\\\}
      escaped_token=${escaped_token//\"/\\\"}
      printf 'url = "%s/api/status"\nheader = "X-Chart-Token: %s"\nfail\nsilent\nshow-error\n' \
        "$CHART_PUBLIC_URL" "$escaped_token" | curl --config - | redact
    else
      echo "CHART_AUTH_TOKEN is unavailable" >&2
      exit 4
    fi
    ;;
  container-state)
    [[ ${#args[@]} -eq 1 ]] || { echo "usage: container-state" >&2; exit 2; }
    container=$(resolve_container)
    docker inspect --format \
      'name={{.Name}} image={{.Config.Image}} status={{.State.Status}} started={{.State.StartedAt}} restarts={{.RestartCount}} oom={{.State.OOMKilled}} exit={{.State.ExitCode}}' \
      "$container"
    ;;
  recent-deploy)
    [[ ${#args[@]} -eq 1 ]] || { echo "usage: recent-deploy" >&2; exit 2; }
    curl -fsS "$CHART_PUBLIC_URL/api/version"
    printf '\n'
    container=$(resolve_container)
    docker inspect --format 'container_started={{.State.StartedAt}} image={{.Config.Image}}' "$container"
    ;;
  capture-read)
    [[ ${#args[@]} -eq 2 ]] && valid_capture_id "${args[1]}" || {
      echo "usage: capture-read c-XXXXXXXXXXXX" >&2; exit 2;
    }
    container=$(resolve_container)
    docker exec "$container" base64 "/tmp/chart-captures/${args[1]}.png"
    ;;
  capture-delete)
    [[ ${#args[@]} -eq 2 ]] && valid_capture_id "${args[1]}" || {
      echo "usage: capture-delete c-XXXXXXXXXXXX" >&2; exit 2;
    }
    curl -fsS -X DELETE "$CHART_PUBLIC_URL/api/debug/captures/${args[1]}" >/dev/null
    echo "deleted ${args[1]}"
    ;;
  *)
    echo "command not allowed" >&2
    exit 2
    ;;
esac
