#!/bin/bash
# SHIFTDECK Container-Watchdog (v6.67+)
# ==================================================================
# Prüft alle 2 Minuten ob die 3 Container (backend, frontend, mongo)
# laufen. Falls einer fehlt: docker compose up -d.
#
# Wird per systemd-Service periodisch aufgerufen.
# Pfad: /opt/shiftdeck/bin/shiftdeck-watchdog
# ==================================================================

INSTALL_DIR="${INSTALL_DIR:-/opt/shiftdeck}"
COMPOSE_FILE="$INSTALL_DIR/docker-compose.prod.yml"
LOG_FILE="$INSTALL_DIR/updates/watchdog.log"

mkdir -p "$(dirname "$LOG_FILE")"

log() {
    echo "[$(date +%Y-%m-%dT%H:%M:%S)] $1" >> "$LOG_FILE"
    # Log-Rotation: max 500 Zeilen behalten
    if [ "$(wc -l < "$LOG_FILE" 2>/dev/null || echo 0)" -gt 500 ]; then
        tail -n 200 "$LOG_FILE" > "$LOG_FILE.tmp" && mv "$LOG_FILE.tmp" "$LOG_FILE"
    fi
}

# Prüfe ob ein Update gerade läuft — dann nicht einmischen.
# v6.80: Bei 5+ Min Stillstand AKTIV reparieren statt nur Status zu ändern.
if [ -f "$INSTALL_DIR/updates/status.json" ]; then
    STAGE=$(grep -oP '"stage"\s*:\s*"\K[^"]+' "$INSTALL_DIR/updates/status.json" 2>/dev/null || echo "")
    case "$STAGE" in
        backup|download|extract|install|build|restart|verify|recovering|starting)
            STATUS_AGE=$(( $(date +%s) - $(stat -c %Y "$INSTALL_DIR/updates/status.json" 2>/dev/null || echo 0) ))
            # v6.80: Build-Phase darf länger dauern (5-7 Min normal),
            # alle anderen Phasen sollten innerhalb 2 Min Status updaten.
            MAX_AGE=300  # 5 Min für die meisten Phasen
            if [ "$STAGE" = "build" ]; then
                MAX_AGE=480  # 8 Min Toleranz für Build-Phase
            fi
            if [ "$STATUS_AGE" -lt "$MAX_AGE" ]; then
                exit 0
            fi

            # Status-File älter als $MAX_AGE → AKTIVE RECOVERY
            log "⚠ Update hängt seit ${STATUS_AGE}s (stage=$STAGE, max=$MAX_AGE) — AKTIVE RECOVERY startet"

            # 1. Hängende Update-Prozesse killen
            log "  → Kille hängende Update-Prozesse..."
            pkill -9 -f "do-update.sh" 2>/dev/null || true
            pkill -9 -f "shiftdeck-update" 2>/dev/null || true
            pkill -9 -f "docker.*compose.*build" 2>/dev/null || true
            pkill -9 -f "docker.*compose.*stop" 2>/dev/null || true
            sleep 2

            # 2. Container hart entfernen falls in inkonsistentem Zustand
            log "  → Entferne potentiell defekte Container..."
            timeout 15 docker rm -f admin-server-backend admin-server-frontend 2>/dev/null || true

            # 3. Container neu starten — Files sind ja schon auf der Disk
            log "  → Starte Container neu..."
            cd "$INSTALL_DIR" || exit 0
            COMPOSE_FILE="docker-compose.prod.yml"
            [ ! -f "$COMPOSE_FILE" ] && COMPOSE_FILE="docker-compose.yml"
            timeout 60 docker compose -f "$COMPOSE_FILE" up -d --remove-orphans 2>&1 | tail -5 | while read l; do log "    $l"; done

            # 4. Erfolg verifizieren
            sleep 8
            if docker ps --format '{{.Names}}' 2>/dev/null | grep -qx 'admin-server-backend'; then
                INSTALLED=$(docker exec admin-server-backend cat /app/VERSION 2>/dev/null | tr -d '[:space:]' || echo "unknown")
                log "  ✓ Recovery erfolgreich, Version: $INSTALLED"
                cat > "$INSTALL_DIR/updates/status.json" <<EOF
{"stage":"success","running":false,"progress":100,"message":"Update wurde automatisch repariert (Version $INSTALLED)","recovered_by_watchdog":true,"current_version":"$INSTALLED"}
EOF
            else
                log "  ✗ Container nicht hochgekommen — bleibt stale"
                cat > "$INSTALL_DIR/updates/status.json" <<EOF
{"stage":"stale","running":false,"progress":0,"message":"Update hing seit ${STATUS_AGE}s — automatische Reparatur fehlgeschlagen","recoverable":true}
EOF
            fi
            exit 0
            ;;
    esac
fi

# Prüfe ob erwartete Container laufen
MISSING=()
for name in admin-server-backend admin-server-frontend admin-server-mongo; do
    if ! docker ps --format '{{.Names}}' 2>/dev/null | grep -qx "$name"; then
        MISSING+=("$name")
    fi
done

# Auch Prefix-Container sind ein Problem (indiziert gescheitertes Update)
PREFIXED=()
for name in $(docker ps -a --format '{{.Names}}' 2>/dev/null | grep -E '_admin-server-(backend|frontend|mongo)$' || true); do
    PREFIXED+=("$name")
done

if [ ${#MISSING[@]} -eq 0 ] && [ ${#PREFIXED[@]} -eq 0 ]; then
    # Alles gut
    exit 0
fi

log "Watchdog: ${#MISSING[@]} Container fehlen, ${#PREFIXED[@]} Prefix-Reste gefunden"

# Prefix-Container wegräumen
for c in "${PREFIXED[@]}"; do
    log "Entferne verwaisten Container: $c"
    docker rm -f "$c" >/dev/null 2>&1 || true
done

# Fehlende starten
if [ ${#MISSING[@]} -gt 0 ]; then
    log "Starte Container mit docker compose up -d"
    OUTPUT=$(docker compose -f "$COMPOSE_FILE" up -d 2>&1)
    log "Compose-Output: $(echo "$OUTPUT" | tail -3 | tr '\n' ' ')"
fi

exit 0
