#!/usr/bin/env bash
# Seit dem 23.09.2026 sind die Webserver aus dem Internet nur noch fuer
# 94.31.93.15 per SSH erreichbar (Cloud-Firewall). Von hier aus laeuft der
# Zugang ueber das INTERNE Netz - dieser Server (10.0.0.6) haengt im selben
# Netzwerk. Deshalb 10.0.1.1 und 10.0.1.2 statt der oeffentlichen Adressen,
# und Frontend 2 braucht keinen Umweg ueber Frontend 1 mehr.
# Sichert das bestehende Shopware 6.6 auf dem Produktionsverbund (2 Frontends,
# 3 Galera-Knoten, Redis, Object Storage) in ein wiederherstellbares Paket.
#
# Läuft auf dem Management-Server und redet über SSH mit den Knoten. Die
# Passwörter stehen NICHT im Skript, sondern in einzelnen Dateien:
#   <zugangsordner>/{fe1,fe2,db1,db2,db3,redis}
#
# Aufruf:  altsystem-export.sh <zugangsordner> [zielordner]
set -euo pipefail

ACCESS="${1:?Zugangsordner fehlt}"
if [ -n "${2:-}" ]; then
    # Vorhandenes Paket weiterführen: Zeitstempel steckt im Ordnernamen
    TARGET="$2"
    STAMP="$(basename "$TARGET" | grep -oE '[0-9]{8}-[0-9]{4}$' || date +%Y%m%d-%H%M)"
else
    STAMP="$(date +%Y%m%d-%H%M)"
    TARGET="/var/backups/riccardo-prod-altsystem-$STAMP"
fi

FE1_INT=10.0.1.1
FE2=10.0.1.2
DB1=10.0.3.1
DB2=10.0.3.2
DB3=10.0.3.3
REDIS=10.0.2.1

SSHO=(-n -o StrictHostKeyChecking=no -o UserKnownHostsFile="$TARGET/known_hosts" -o ConnectTimeout=15 -o ServerAliveInterval=30 -o ExitOnForwardFailure=yes)
SCPO=(-o StrictHostKeyChecking=no -o UserKnownHostsFile="$TARGET/known_hosts" -o ConnectTimeout=15 -o ServerAliveInterval=30)
REMOTE_WORK=/var/backups/shopware-6.6-export

mkdir -p "$TARGET"/{datenbank,code,system,inventar}
touch "$TARGET/known_hosts"

log() { printf '\n\033[1m== %s\033[0m\n' "$*"; }

# Befehl auf einem Knoten ausführen (alles außer FE1 über FE1 als Sprungserver)
on() {
    local key="$1" host="$2"; shift 2
    [ -n "$host" ] && [ $# -gt 0 ] || { echo "on(): Host oder Befehl fehlt ($key)" >&2; return 2; }
    if [ "$key" = fe1 ]; then
        sshpass -f "$ACCESS/fe1" ssh "${SSHO[@]}" "root@$FE1_INT" "$@"
    else
        sshpass -f "$ACCESS/$key" ssh "${SSHO[@]}" \
            -o ProxyCommand="sshpass -f $ACCESS/fe1 ssh ${SCPO[*]} -W %h:%p root@$FE1_INT" \
            "root@$host" "$@"
    fi
}

# Datei von einem Knoten holen
pull() {
    local key="$1" host="$2" remote="$3" local="$4"
    if [ "$key" = fe1 ]; then
        sshpass -f "$ACCESS/fe1" scp "${SCPO[@]}" "root@$FE1_INT:$remote" "$local"
    else
        sshpass -f "$ACCESS/$key" scp "${SCPO[@]}" \
            -o ProxyCommand="sshpass -f $ACCESS/fe1 ssh ${SCPO[*]} -W %h:%p root@$FE1_INT" \
            "root@$host:$remote" "$local"
    fi
}

# ------------------------------------------------------------------ Datenbank
have() { [ -s "$1" ]; }

log "Datenbank-Dumps auf DB-SRV-1 erzeugen (Galera, 3 Knoten)"
on db1 "$DB1" "mkdir -p $REMOTE_WORK && cd $REMOTE_WORK && \
    for db in shopware stores_website; do \
        echo \"  \$db ...\"; \
        mariadb-dump --single-transaction --quick --routines --triggers --events \
            --default-character-set=utf8mb4 --databases \$db \
            | gzip -6 > \$db-$STAMP.sql.gz; \
    done; ls -la $REMOTE_WORK"

log "Dumps abholen"
for db in shopware stores_website; do
    have "$TARGET/datenbank/$db-$STAMP.sql.gz" || pull db1 "$DB1" "$REMOTE_WORK/$db-$STAMP.sql.gz" "$TARGET/datenbank/"
done

log "Cluster-Zustand und Datenbank-Konfiguration festhalten"
on db1 "$DB1" 'mariadb -e "show status like \"wsrep_cluster%\"; show status like \"wsrep_local_state_comment\"; select @@version, @@server_id;"; \
    echo; echo "-- Tabellen nach Größe"; \
    mariadb -e "select table_schema, table_name, round((data_length+index_length)/1024/1024,1) MB, table_rows from information_schema.tables where table_schema in (\"shopware\",\"stores_website\") order by (data_length+index_length) desc limit 25"' \
    > "$TARGET/inventar/datenbank-zustand.txt"
for n in db1:$DB1 db2:$DB2 db3:$DB3; do
    key="${n%%:*}"; host="${n##*:}"
    on "$key" "$host" 'hostname; echo "--- Konfiguration"; cat /etc/mysql/mariadb.conf.d/*.cnf 2>/dev/null; cat /etc/mysql/conf.d/*.cnf 2>/dev/null' \
        > "$TARGET/system/mariadb-$key.txt"
done

# ----------------------------------------------------------------------- Code
log "Code und Konfiguration auf WEB-SRV-1 verpacken (ohne Logs, Cache, vendor)"
on fe1 "$FE1_INT" "mkdir -p $REMOTE_WORK && cd /var/www && \
    tar czf $REMOTE_WORK/shopware-code-$STAMP.tar.gz \
        --exclude=shopware/var/log --exclude=shopware/var/cache \
        --exclude=shopware/vendor --exclude=shopware/node_modules \
        --exclude='*/node_modules' shopware && \
    tar czf $REMOTE_WORK/stores-app-$STAMP.tar.gz --exclude=stores/storage/logs --exclude='*/node_modules' stores gutschein && \
    ls -la $REMOTE_WORK"

log "Code-Pakete abholen"
have "$TARGET/code/shopware-code-$STAMP.tar.gz" || pull fe1 "$FE1_INT" "$REMOTE_WORK/shopware-code-$STAMP.tar.gz" "$TARGET/code/"
have "$TARGET/code/stores-app-$STAMP.tar.gz" || pull fe1 "$FE1_INT" "$REMOTE_WORK/stores-app-$STAMP.tar.gz" "$TARGET/code/"

log "Zweites Frontend: Unterschiede und eigene Konfiguration"
on fe2 "$FE2" 'cd /var/www 2>/dev/null && ls -la; echo "--- Shopware vorhanden?"; \
    (grep -m1 "\"shopware/core\"" /var/www/shopware/composer.json 2>/dev/null || echo "kein Shopware unter /var/www/shopware"); \
    echo "--- Prüfsummen wichtiger Dateien"; \
    md5sum /var/www/shopware/.env.local /var/www/shopware/composer.lock 2>/dev/null; \
    echo "--- nginx"; ls /etc/nginx/sites-enabled/; echo "--- Dienste"; \
    systemctl list-unit-files 2>/dev/null | grep -iE "shopware|riccardo"' \
    > "$TARGET/inventar/frontend-2.txt" || true
on fe1 "$FE1_INT" "md5sum /var/www/shopware/.env.local /var/www/shopware/composer.lock" > "$TARGET/inventar/frontend-1-pruefsummen.txt"

# --------------------------------------------------------------------- System
log "Systemkonfiguration beider Frontends und des Redis-Knotens einsammeln"
for n in fe1:$FE1_INT fe2:$FE2; do
    key="${n%%:*}"; host="${n##*:}"
    on "$key" "$host" 'hostname; hostname -I; echo "=== nginx ==="; cat /etc/nginx/sites-enabled/*.conf; \
        echo "=== php-fpm pool ==="; cat /etc/php/*/fpm/pool.d/*.conf; \
        echo "=== php.ini (abweichende Werte) ==="; php -i | grep -E "^(memory_limit|max_execution_time|upload_max_filesize|post_max_size|opcache.enable|date.timezone)"; \
        echo "=== systemd units ==="; for u in shopware-worker@.service shopware-scheduler.service riccardo-worker.service; do echo "--- $u"; systemctl cat $u 2>/dev/null; done; \
        echo "=== aktivierte Units ==="; systemctl list-unit-files --state=enabled --no-pager | grep -iE "shopware|riccardo|nginx|php"; \
        echo "=== crontabs ==="; crontab -l 2>/dev/null; crontab -u www-data -l 2>/dev/null; \
        echo "=== Pakete ==="; dpkg -l | awk "/^ii/{print \$2\" \"\$3}" | grep -E "php|nginx|mariadb|redis|opensearch"' \
        > "$TARGET/system/$key-system.txt" || true
done
on redis "$REDIS" 'hostname; echo "=== redis.conf (ohne Kommentare) ==="; grep -vE "^#|^$" /etc/redis/redis.conf; \
    echo "=== Info ==="; redis-cli -a "$(grep -m1 ^requirepass /etc/redis/redis.conf | awk "{print \$2}")" --no-auth-warning info keyspace 2>/dev/null | head -20' \
    > "$TARGET/system/redis-system.txt" || true

# ------------------------------------------------------------------- Inventar
log "Shopware-Inventar (Plugins, Verkaufskanäle, Object Storage)"
on fe1 "$FE1_INT" "cd /var/www/shopware && php bin/console plugin:list 2>/dev/null" > "$TARGET/inventar/plugins.txt" || true
on fe1 "$FE1_INT" "cd /var/www/shopware && cat composer.json" > "$TARGET/inventar/composer.json" || true
on fe1 "$FE1_INT" "cd /var/www/shopware && grep -E '\"(name|version)\"' composer.lock | head -0; php -r '\$l=json_decode(file_get_contents(\"composer.lock\"),true); foreach(\$l[\"packages\"] as \$p){ printf(\"%-50s %s\n\", \$p[\"name\"], \$p[\"version\"]); }'" > "$TARGET/inventar/composer-pakete.txt" || true

log "Object-Storage-Inventar (kein Kopieren, nur Verzeichnis)"
on fe1 "$FE1_INT" 'cd /var/www/shopware && export AWS_ACCESS_KEY_ID=$(grep -m1 ^S3_KEY= .env.local | cut -d= -f2) \
    AWS_SECRET_ACCESS_KEY=$(grep -m1 ^S3_SECRET= .env.local | cut -d= -f2); \
    EP=$(grep -m1 ^S3_ENDPOINT= .env.local | cut -d= -f2); \
    for b in $(grep -E "^S3_BUCKET" .env.local | cut -d= -f2 | tr -d "\"" | sort -u); do \
        echo "===== Bucket $b"; aws --endpoint-url $EP s3 ls --recursive --summarize s3://$b; \
    done' > "$TARGET/inventar/objectstorage-inventar.txt" || true

log "Prüfsummen"
( cd "$TARGET" && find datenbank code -type f -exec sha256sum {} \; > inventar/pruefsummen.sha256 )

log "Fertig: $TARGET"
du -sh "$TARGET"/* | sort -h
