#!/usr/bin/env bash
# AutoSeg Viewer + Agfa Enterprise Imaging (ambiente demo.agfa.net)
#
#   bash agfa.sh teste    SECRET   testa login e DICOMweb do Agfa, como o viewer faz
#   bash agfa.sh instalar SECRET   instala/atualiza o viewer ligado ao Agfa
#
# O SECRET é o client secret do Keycloak do Agfa (32 caracteres), NÃO o token
# (eyJ...). Nada aqui grava o secret em disco; o instalador o guarda num Secret
# do Kubernetes. A saída mostra só códigos HTTP, contagens e UIDs, sem nomes.
set -u

ACAO=${1:-}
SEC=$(printf '%s' "${2:-}" | tr -d '[:space:]')
[ $# -ge 2 ] && shift 2 || shift $#

CID=${AGFA_CLIENT_ID:-xeroticket}
H=${AGFA_HOST:-ahei01.demo.agfa.net}
IP=${AGFA_IP:-192.168.93.5}
VM=${VIEWER_IP:-192.168.93.202}
VER=${VIEWER_VERSION:-1.4.6}
TURL=${AGFA_TOKEN_URL:-https://$H:1243/auth/realms/EI/protocol/openid-connect/token}
BASE=${AGFA_DICOMWEB:-https://$H/dicom-web}
CAF=${AGFA_CA:-/root/ca-agfa.pem}
PKG=https://pkg.rtmedical.ai/api/packages/apps/generic/viewer

die() { echo "ERRO: $*" >&2; exit 1; }
uso() { sed -n '4,5p' "$0" | sed 's/^# *//'; exit 1; }

case $ACAO in teste|instalar) ;; *) uso ;; esac
[ -n "$SEC" ] || die "falta o secret. Ex.: bash agfa.sh $ACAO 9mne...Comh"
case $SEC in eyJ*|*eyJhbGci*) die "isso é (ou contém) o TOKEN, não o secret. Use só o client secret de 32 caracteres." ;; esac
[ ${#SEC} -eq 32 ] || echo "aviso: o secret tem ${#SEC} caracteres (o do Keycloak costuma ter 32)."

# Certificados do Agfa (porta 443 e 1243), usados como "CA" do PACS.
garantir_ca() {
  if grep -q 'BEGIN CERT' "$CAF" 2>/dev/null; then return 0; fi
  echo "criando $CAF com os certificados do $H ..."
  : > "$CAF"
  for p in 443 1243; do
    echo | openssl s_client -connect "$IP:$p" -servername "$H" 2>/dev/null | openssl x509 >> "$CAF" 2>/dev/null
  done
  grep -q 'BEGIN CERT' "$CAF" || die "não consegui ler o certificado do $H ($IP)"
}

TMP=$(mktemp -d); trap 'rm -rf "$TMP"' EXIT
TLS=(--cacert "$CAF")
# O nome do Agfa não tem DNS: resolve $H -> $IP em cada porta usada pelas URLs.
porta() { local u=${1#*://}; u=${u%%/*}
  case $u in *:*) echo "${u##*:}" ;; *) case $1 in https:*) echo 443 ;; *) echo 80 ;; esac ;; esac; }
RES=(); for p in $(printf '%s\n' "$(porta "$TURL")" "$(porta "$BASE")" | sort -u); do RES+=(--resolve "$H:$p:$IP"); done
c() { curl -sS -m 30 "${RES[@]}" "${TLS[@]}" "$@"; }
tok() { c -X POST "$TURL" --data-urlencode grant_type=client_credentials \
          --data-urlencode "client_id=$CID" --data-urlencode "client_secret=$SEC"; }

PY=$(command -v python3 || command -v /usr/libexec/platform-python || true)
# pick TAG MODALIDADES -> "<quantidade> <valor da TAG no 1º item, preferindo as modalidades>"
pick() {
  [ -n "$PY" ] || { echo "? -"; return; }
  "$PY" -c '
import json,sys
tag,pref=sys.argv[1],sys.argv[2].split(",")
try: d=json.load(open(sys.argv[3]))
except Exception: print("0 -"); sys.exit()
if not isinstance(d,list): print("0 -"); sys.exit()
def v(x,t):
    try: return x[t]["Value"][0]
    except Exception: return ""
best=[x for x in d if v(x,"00080060") in pref] or d
print(len(d), (v(best[0],tag) or "-") if best else "-")
' "$1" "$2" "$TMP/r.json"
}
# q ROTULO URL -> GET com token; mostra HTTP e, se não for 200, o começo da resposta
q() {
  local code
  code=$(c -H "Authorization: Bearer $TOK" -H 'Accept: application/dicom+json' \
           -o "$TMP/r.json" -w '%{http_code}' "$2")
  echo "$1: HTTP $code, $(wc -c < "$TMP/r.json" 2>/dev/null || echo 0) bytes"
  if [ "$code" != 200 ]; then head -c 300 "$TMP/r.json" 2>/dev/null; echo; return 1; fi
}

teste() {
  garantir_ca
  echo "== 1. token ($CID)"
  local j rc; j=$(tok 2>&1); rc=$?
  case $rc in 35|51|53|54|58|59|60|64|66|77|80|82|83|90|91)
    echo "o certificado do Agfa NÃO confere com $CAF (curl $rc): $(printf '%s' "$j" | head -c 200)"
    echo "repetindo sem verificar o certificado, só para ver se o resto funciona..."
    TLS=(-k); j=$(tok 2>&1) ;;
  esac
  TOK=$(printf '%s' "$j" | sed -n 's/.*"access_token" *: *"\([^"]*\)".*/\1/p')
  if [ -z "$TOK" ]; then echo "token: FALHOU"; printf '%s\n' "$j" | head -c 300; echo; exit 1; fi
  echo "token: ok (${#TOK} caracteres), TLS: ${TLS[*]}"
  echo "== 2. busca de estudos (QIDO)"
  q estudos "$BASE/studies?limit=10" || exit 1
  local n st se sop
  read -r n st <<< "$(pick 0020000D x)"; echo "estudos: $n, primeiro: $st"
  [ "$st" != "-" ] || { echo "nenhum estudo retornado"; exit 1; }
  echo "== 3. séries"
  q series "$BASE/studies/$st/series" || exit 1
  read -r n se <<< "$(pick 0020000E CT,MR)"; echo "séries: $n, escolhida: $se"
  echo "== 4. metadados (WADO-RS)"
  q metadados "$BASE/studies/$st/series/$se/metadata"
  echo "== 5. imagem (WADO-RS)"
  q instancias "$BASE/studies/$st/series/$se/instances" || exit 1
  read -r n sop <<< "$(pick 00080018 x)"; echo "imagens na série: $n"
  c -H "Authorization: Bearer $TOK" -H 'Accept: multipart/related; type="application/dicom"' \
    -o "$TMP/i.bin" -w 'imagem: HTTP %{http_code}, %{size_download} bytes\n' \
    "$BASE/studies/$st/series/$se/instances/$sop"
  echo "== link do estudo no viewer"
  echo "https://$VM/viewer/launch?url=$BASE/studies/$st"
}

instalar() {
  garantir_ca
  cd "$TMP" || die "sem diretório temporário"
  curl -fsSLo install-viewer.sh "$PKG/$VER/install-viewer.sh" || die "não baixei o instalador $VER"
  curl -fsSLo SHA256SUMS "$PKG/$VER/SHA256SUMS" || die "não baixei o SHA256SUMS"
  sha256sum -c SHA256SUMS || die "SHA-256 do instalador não confere"
  bash install-viewer.sh --yes --ip "$VM" \
    --pacs-host "$H=$IP" \
    --pacs-url "$BASE" \
    --pacs-token-url "$TURL" \
    --pacs-client-id "$CID" \
    --pacs-client-secret "$SEC" \
    --pacs-ca "$CAF" "$@"
}

"$ACAO" "$@"
