#!/bin/sh
# GerbilManager Deploy-Skript (laeuft auf der TrueNAS Goldeye)
# ===========================================================
# Holt die neuen Images aus der Gitea-Registry und rollt den Compose-Stack neu aus.
# Wird vom Gitea-Actions 'deploy'-Job (self-hosted Runner auf der NAS) aufgerufen
# UND kann jederzeit manuell auf der NAS ausgefuehrt werden:
#
#   sh /opt/gerbilmanager/deploy/truenas/scripts/deploy.sh
#   TAG=<git-sha> sh .../deploy.sh        # Rollback auf ein bestimmtes Image
#   GIT_PULL=0   sh .../deploy.sh        # ohne 'git pull' (nur Images neu ziehen)
#
# Konfiguration ueber Umgebungsvariablen (alle optional, sinnvolle Defaults):
#   COMPOSE_DIR     Installationsverzeichnis (Default: /opt/gerbilmanager)
#   TAG             Image-Tag (Default: latest; fuer Rollback z. B. ein git-SHA)
#   GIT_PULL        1 = vorher 'git pull' (Default), 0 = ueberspringen
#   HEALTH_TIMEOUT  Sekunden auf api-Healthcheck warten (Default: 180)
#   REGISTRY / REGISTRY_USER / REGISTRY_TOKEN  optionaler docker login vor dem Pull
set -eu

COMPOSE_DIR="${COMPOSE_DIR:-/opt/gerbilmanager}"
COMPOSE_FILE="$COMPOSE_DIR/deploy/truenas/compose.yaml"
TAG="${TAG:-latest}"
GIT_PULL="${GIT_PULL:-1}"
HEALTH_TIMEOUT="${HEALTH_TIMEOUT:-180}"
REGISTRY="${REGISTRY:-git.rismer.de}"

log() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1"; }
fail() { log "FEHLER: $1"; exit 1; }

export TAG   # compose interpoliert ${TAG} in den Image-Referenzen

log "=== Deploy gestartet (TAG=$TAG, dir=$COMPOSE_DIR) ==="

[ -f "$COMPOSE_FILE" ] || fail "compose.yaml nicht gefunden: $COMPOSE_FILE"
command -v docker >/dev/null 2>&1 || fail "docker nicht im PATH des Runners"
docker compose version >/dev/null 2>&1 || fail "'docker compose' (v2) nicht verfuegbar"

cd "$COMPOSE_DIR"

# --- 1. Repo aktualisieren (compose.yaml / Skripte / Docs) ---
if [ "$GIT_PULL" = "1" ] && [ -d "$COMPOSE_DIR/.git" ]; then
    log "git pull --ff-only ..."
    git -C "$COMPOSE_DIR" pull --ff-only || log "WARNUNG: git pull fehlgeschlagen — fahre mit vorhandenem Stand fort"
fi

# --- 2. Registry-Login (nur wenn Credentials uebergeben wurden) ---
if [ -n "${REGISTRY_USER:-}" ] && [ -n "${REGISTRY_TOKEN:-}" ]; then
    log "docker login $REGISTRY ..."
    echo "$REGISTRY_TOKEN" | docker login "$REGISTRY" -u "$REGISTRY_USER" --password-stdin >/dev/null \
        || fail "docker login fehlgeschlagen"
fi

# --- 3. Neue Images ziehen ---
log "Ziehe Images (Tag: $TAG) ..."
docker compose -f "$COMPOSE_FILE" pull || fail "docker compose pull fehlgeschlagen"

# --- 4. Stack neu ausrollen (nur geaenderte Container werden neu erstellt) ---
log "Rolle Stack aus (up -d) ..."
docker compose -f "$COMPOSE_FILE" up -d --remove-orphans || fail "docker compose up fehlgeschlagen"

# --- 5. Auf api-Healthcheck warten (impliziert db gesund) ---
log "Warte auf api-Healthcheck (max ${HEALTH_TIMEOUT}s) ..."
API_CID="$(docker compose -f "$COMPOSE_FILE" ps -q api)"
[ -n "$API_CID" ] || fail "api-Container nicht gefunden"

elapsed=0
while :; do
    state="$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' "$API_CID" 2>/dev/null || echo unknown)"
    case "$state" in
        healthy) log "api ist gesund."; break ;;
        none|unknown)
            # Kein Healthcheck definiert/lesbar -> auf laufenden Zustand zurueckfallen.
            running="$(docker inspect --format '{{.State.Running}}' "$API_CID" 2>/dev/null || echo false)"
            [ "$running" = "true" ] && { log "api laeuft (kein Healthcheck-Status lesbar)."; break; }
            ;;
    esac
    if [ "$elapsed" -ge "$HEALTH_TIMEOUT" ]; then
        log "Letzte api-Logs:"; docker compose -f "$COMPOSE_FILE" logs --tail 40 api || true
        fail "api wurde nicht innerhalb ${HEALTH_TIMEOUT}s gesund (Status: $state)"
    fi
    sleep 5; elapsed=$((elapsed + 5))
done

# --- 6. Alte/ungenutzte Images aufraeumen ---
log "Raeume verwaiste Images auf ..."
docker image prune -f >/dev/null 2>&1 || true

log "Laufende Dienste:"
docker compose -f "$COMPOSE_FILE" ps --format 'table {{.Service}}\t{{.Status}}' 2>/dev/null \
    || docker compose -f "$COMPOSE_FILE" ps
log "=== Deploy erfolgreich abgeschlossen (TAG=$TAG) ==="
