#!/usr/bin/bash
##
#
# MedArch Server - Verwaltungstool
#
# Verwendung:
#   medarch status      - Zeigt Status aller Services
#   medarch start       - Startet alle Services
#   medarch stop        - Stoppt alle Services
#   medarch restart     - Startet alle Services neu
#   medarch logs        - Zeigt Live-Logs aller Services
#   medarch update      - Fuehrt Update aus (Migration + Neustart)
#   medarch upgrade     - Prueft und installiert RPM-Updates
#   medarch backup      - Erstellt vollstaendiges Backup
#   medarch version     - Zeigt Version und Update-Status
#   medarch health      - Fuehrt Health-Check durch
#   medarch rollback    - Stellt letztes Backup wieder her
#   medarch autoupdate  - Automatische Updates konfigurieren (auto/manuell)
#
# Installation:
#   cp /opt/medarch/medarch /usr/local/bin/medarch
#   chmod +x /usr/local/bin/medarch
#
# Copyright (c) Christof Poschadel 2023 - 2026
#
##

SERVICES=(medarch-api medarch-chat medarch-form-gateway medarch-fax)
INSTALL_DIR="/opt/medarch"
BACKUP_DIR="/opt/medarch/backups"
LOG_DIR="/var/log/medarch"
VERSION_FILE="$INSTALL_DIR/.version"

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
DIM='\033[2m'
NC='\033[0m'

# =========================================================================
#  Hilfsfunktionen
# =========================================================================

require_root() {
    if [ "$EUID" -ne 0 ]; then
        echo -e "${RED}Dieser Befehl erfordert root-Rechte.${NC}"
        echo "Verwende: sudo medarch $1"
        exit 1
    fi
}

get_version() {
    if [ -f "$VERSION_FILE" ]; then
        cat "$VERSION_FILE"
    else
        echo "unbekannt"
    fi
}

health_check() {
    local HOST="${1:-localhost}"
    local ALL_OK=true

    echo ""
    echo -e "${BOLD}MedArch Health-Check${NC}"
    echo "──────────────────────────────────────────"

    # API-Server
    HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://${HOST}:8000/" --connect-timeout 3 2>/dev/null || echo "000")
    if [ "$HTTP_CODE" = "200" ]; then
        echo -e "  ${GREEN}●${NC} API-Server (Port 8000)    ${GREEN}HTTP $HTTP_CODE${NC}"
    else
        echo -e "  ${RED}●${NC} API-Server (Port 8000)    ${RED}HTTP $HTTP_CODE${NC}"
        ALL_OK=false
    fi

    # Chat TCP
    if ss -tlnp 2>/dev/null | grep -q ":1235 "; then
        echo -e "  ${GREEN}●${NC} Chat TCP (Port 1235)      ${GREEN}lauscht${NC}"
    else
        echo -e "  ${RED}●${NC} Chat TCP (Port 1235)      ${RED}nicht erreichbar${NC}"
        ALL_OK=false
    fi

    # Chat WebSocket
    if ss -tlnp 2>/dev/null | grep -q ":8765 "; then
        echo -e "  ${GREEN}●${NC} Chat WebSocket (8765)     ${GREEN}lauscht${NC}"
    else
        echo -e "  ${RED}●${NC} Chat WebSocket (8765)     ${RED}nicht erreichbar${NC}"
        ALL_OK=false
    fi

    # Form Gateway
    HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://${HOST}:8080/" --connect-timeout 3 2>/dev/null || echo "000")
    if [ "$HTTP_CODE" != "000" ]; then
        echo -e "  ${GREEN}●${NC} Form Gateway (Port 8080)  ${GREEN}HTTP $HTTP_CODE${NC}"
    else
        echo -e "  ${RED}●${NC} Form Gateway (Port 8080)  ${RED}nicht erreichbar${NC}"
        ALL_OK=false
    fi

    # Datenbank
    DB_USER=$(grep -oP 'DB_USER=\K.*' "$INSTALL_DIR/.env" 2>/dev/null || echo "medarch")
    DB_PASS=$(grep -oP 'DB_PASSWORD=\K.*' "$INSTALL_DIR/.env" 2>/dev/null || echo "")
    DB_NAME=$(grep -oP 'DB_NAME=\K.*' "$INSTALL_DIR/.env" 2>/dev/null || echo "medarch")

    if [ -n "$DB_PASS" ]; then
        DB_CHECK=$(mysql -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "SELECT 1" -sN 2>/dev/null || echo "")
    else
        DB_CHECK=$(mysql -u "$DB_USER" "$DB_NAME" -e "SELECT 1" -sN 2>/dev/null || echo "")
    fi

    if [ "$DB_CHECK" = "1" ]; then
        echo -e "  ${GREEN}●${NC} Datenbank (MySQL)         ${GREEN}verbunden${NC}"
    else
        echo -e "  ${RED}●${NC} Datenbank (MySQL)         ${RED}nicht erreichbar${NC}"
        ALL_OK=false
    fi

    # Disk-Space
    DISK_USAGE=$(df -h /opt/medarch 2>/dev/null | tail -1 | awk '{print $5}' | tr -d '%')
    if [ -n "$DISK_USAGE" ] && [ "$DISK_USAGE" -lt 90 ]; then
        echo -e "  ${GREEN}●${NC} Speicherplatz              ${GREEN}${DISK_USAGE}% belegt${NC}"
    elif [ -n "$DISK_USAGE" ]; then
        echo -e "  ${YELLOW}●${NC} Speicherplatz              ${YELLOW}${DISK_USAGE}% belegt${NC}"
    fi

    echo "──────────────────────────────────────────"

    if [ "$ALL_OK" = true ]; then
        echo -e "  ${GREEN}${BOLD}Alles in Ordnung!${NC}"
    else
        echo -e "  ${RED}${BOLD}Es gibt Probleme - siehe oben.${NC}"
    fi
    echo ""

    $ALL_OK
}

# =========================================================================
#  Befehle
# =========================================================================

case "$1" in

    status)
        echo ""
        echo -e "${BOLD}MedArch Server Status${NC}  ${DIM}(Version: $(get_version))${NC}"
        echo "──────────────────────────────────────────"
        for service in "${SERVICES[@]}"; do
            STATUS=$(systemctl is-active "$service" 2>/dev/null || echo "nicht installiert")
            if [ "$STATUS" = "active" ]; then
                UPTIME=$(systemctl show "$service" --property=ActiveEnterTimestamp --value 2>/dev/null)
                MEM=$(systemctl show "$service" --property=MemoryCurrent --value 2>/dev/null)
                if [ "$MEM" != "[not set]" ] && [ -n "$MEM" ] && [ "$MEM" != "infinity" ]; then
                    MEM_MB=$((MEM / 1048576))
                    echo -e "  ${GREEN}●${NC} ${service}  ${GREEN}aktiv${NC}  (seit $UPTIME, ${MEM_MB}MB RAM)"
                else
                    echo -e "  ${GREEN}●${NC} ${service}  ${GREEN}aktiv${NC}  (seit $UPTIME)"
                fi
            else
                echo -e "  ${RED}●${NC} ${service}  ${RED}$STATUS${NC}"
            fi
        done
        echo "──────────────────────────────────────────"
        echo ""

        echo "Ports:"
        for port in 8000 1235 8765 8080; do
            LINE=$(ss -tlnp 2>/dev/null | grep ":${port} " | head -1)
            if [ -n "$LINE" ]; then
                echo -e "  ${GREEN}●${NC} Port $port  belegt"
            else
                echo -e "  ${RED}○${NC} Port $port  frei"
            fi
        done
        echo ""

        # Datenbank-Zeichensatz und Startaufgaben (brauchen Leserechte auf .env und data/)
        if [ -r "$INSTALL_DIR/.env" ]; then
            echo "Prüfungen:"
            for check in db_charset startup_status; do
                LINE=$(cd "$INSTALL_DIR" && timeout 30 python3 "$check.py" 2>/dev/null | grep -E '^(OK|FEHLER):' | tail -5)
                [ -z "$LINE" ] && continue
                while IFS= read -r l; do
                    case "$l" in
                        OK:*) echo -e "  ${GREEN}●${NC} ${l#OK: }" ;;
                        *)    echo -e "  ${RED}●${NC} ${l#FEHLER: }" ;;
                    esac
                done <<< "$LINE"
            done
            echo ""
        fi
        ;;

    start)
        require_root "start"
        echo "Starte MedArch Services..."
        for service in "${SERVICES[@]}"; do
            systemctl start "$service" 2>/dev/null && \
                echo -e "  ${GREEN}✓${NC} $service gestartet" || \
                echo -e "  ${RED}✗${NC} $service Fehler"
        done
        ;;

    stop)
        require_root "stop"
        echo "Stoppe MedArch Services..."
        for service in "${SERVICES[@]}"; do
            systemctl stop "$service" 2>/dev/null && \
                echo -e "  ${GREEN}✓${NC} $service gestoppt" || \
                echo -e "  ${RED}✗${NC} $service Fehler"
        done
        ;;

    restart)
        require_root "restart"
        echo "Starte MedArch Services neu..."
        for service in "${SERVICES[@]}"; do
            systemctl restart "$service" 2>/dev/null && \
                echo -e "  ${GREEN}✓${NC} $service neu gestartet" || \
                echo -e "  ${RED}✗${NC} $service Fehler"
        done
        ;;

    logs)
        SERVICE_NAME="${2:-}"
        LINES="${3:-50}"
        if [ -n "$SERVICE_NAME" ]; then
            journalctl -u "$SERVICE_NAME" -f --no-hostname -n "$LINES"
        else
            journalctl -u medarch-api -u medarch-chat -u medarch-form-gateway -f --no-hostname -n "$LINES"
        fi
        ;;

    update)
        require_root "update"
        echo -e "${BOLD}MedArch Update (lokal)${NC}"
        echo ""

        # Backup
        echo "Erstelle Backup..."
        bash "$INSTALL_DIR/install.sh" --backup-only

        echo "Stoppe Services..."
        for service in "${SERVICES[@]}"; do
            systemctl stop "$service" 2>/dev/null || true
        done

        echo "Aktualisiere Python-Abhaengigkeiten..."
        pip3 install -r "$INSTALL_DIR/requirements.txt" --quiet 2>&1 | grep -v "already satisfied" || true

        echo "Fuehre Datenbank-Migration aus..."
        cd "$INSTALL_DIR"
        if [ -f "migrate_full.py" ]; then
            python3 migrate_full.py
        elif [ -f "tools/migrate_full.py" ]; then
            python3 tools/migrate_full.py
        fi

        echo "Aktualisiere Standard-Daten..."
        if [ -f "db_updater.py" ]; then
            python3 db_updater.py 2>&1 | tail -3
        elif [ -f "tools/db_updater.py" ]; then
            python3 tools/db_updater.py 2>&1 | tail -3
        fi

        echo "Lade Service-Definitionen neu..."
        cp "$INSTALL_DIR/services/"*.service /etc/systemd/system/ 2>/dev/null || true
        systemctl daemon-reload

        echo "Starte Services..."
        for service in "${SERVICES[@]}"; do
            systemctl start "$service" 2>/dev/null && \
                echo -e "  ${GREEN}✓${NC} $service laeuft" || \
                echo -e "  ${RED}✗${NC} $service Fehler"
        done

        echo ""
        echo -e "${GREEN}Update abgeschlossen!${NC}"
        ;;

    upgrade)
        require_root "upgrade"
        echo -e "${BOLD}MedArch Server - RPM Upgrade${NC}"
        echo ""

        # Pruefen ob Updates verfuegbar
        echo "Pruefe auf Updates..."
        AVAILABLE=$(dnf check-update medarch-server 2>/dev/null | grep medarch-server || true)

        if [ -z "$AVAILABLE" ]; then
            echo -e "${GREEN}System ist aktuell - kein Update verfuegbar.${NC}"
            echo ""
            echo "  Installierte Version: $(get_version)"
            RPM_VER=$(rpm -q medarch-server --queryformat '%{VERSION}-%{RELEASE}' 2>/dev/null || echo "nicht als RPM installiert")
            echo "  RPM-Version:          $RPM_VER"
            echo ""
            exit 0
        fi

        echo -e "${YELLOW}Update verfuegbar: $AVAILABLE${NC}"
        echo ""

        # Update ueber den Update-Runner (systemd-Unit): Backup + Verifikation,
        # Migration, Neustart, Health-Check und automatischer Rollback.
        # Laeuft auch weiter, wenn die SSH-Verbindung abbricht.
        python3 "$INSTALL_DIR/update_runner.py" start --type full --follow
        RC=$?
        echo ""
        if [ $RC -eq 0 ]; then
            echo -e "${GREEN}${BOLD}Upgrade abgeschlossen!${NC}"
        else
            echo -e "${RED}${BOLD}Upgrade fehlgeschlagen${NC} - Details: medarch autoupdate history"
        fi
        echo "  Version: $(get_version)"
        echo ""
        echo "  Pruefe mit: medarch health"
        ;;

    backup)
        require_root "backup"
        if [ "$2" = "--auto" ]; then
            # Stiller Modus fuer automatische Backups (z.B. aus RPM %pre)
            bash "$INSTALL_DIR/install.sh" --backup-only 2>/dev/null
        else
            bash "$INSTALL_DIR/install.sh" --backup-only
        fi
        ;;

    health)
        health_check "${2:-localhost}"
        ;;

    version)
        echo ""
        echo -e "${BOLD}MedArch Server${NC}"
        echo "──────────────────────────────────────────"
        echo "  Version:     $(get_version)"
        RPM_VER=$(rpm -q medarch-server --queryformat '%{VERSION}-%{RELEASE}' 2>/dev/null || echo "nicht als RPM")
        echo "  RPM-Paket:   $RPM_VER"
        echo "  Python:      $(python3 --version 2>&1)"
        echo "  Server:      $(hostname)"
        echo "  Uptime:      $(uptime -p 2>/dev/null || uptime)"
        echo "──────────────────────────────────────────"

        # Auf Updates pruefen
        AVAILABLE=$(dnf check-update medarch-server 2>/dev/null | grep medarch-server || true)
        if [ -n "$AVAILABLE" ]; then
            echo ""
            echo -e "  ${YELLOW}Update verfuegbar!${NC}"
            echo "  $AVAILABLE"
            echo ""
            echo "  Installiere mit: sudo medarch upgrade"
        fi
        echo ""
        ;;

    rollback)
        require_root "rollback"
        echo -e "${BOLD}MedArch Server - Rollback${NC}"
        echo ""

        # Letztes Backup finden
        LATEST_BACKUP=$(ls -dt "$BACKUP_DIR"/pre-update_* 2>/dev/null | head -1)

        if [ -z "$LATEST_BACKUP" ]; then
            echo -e "${RED}Kein Backup gefunden!${NC}"
            exit 1
        fi

        echo "Letztes Backup: $LATEST_BACKUP"
        if [ -f "$LATEST_BACKUP/BACKUP_INFO.txt" ]; then
            echo ""
            cat "$LATEST_BACKUP/BACKUP_INFO.txt" | head -5
        fi

        echo ""
        echo -e "${YELLOW}ACHTUNG: Dies stellt die vorherige Version wieder her!${NC}"
        read -p "Fortfahren? (j/N) " -n 1 -r
        echo ""

        if [[ ! $REPLY =~ ^[Jj]$ ]]; then
            echo "Abgebrochen."
            exit 0
        fi

        echo ""
        echo "Stoppe Services..."
        for service in "${SERVICES[@]}"; do
            systemctl stop "$service" 2>/dev/null || true
        done

        # Datenbank wiederherstellen
        if [ -f "$LATEST_BACKUP/database.sql.gz" ]; then
            echo "Stelle Datenbank wieder her..."
            DB_USER=$(grep -oP 'DB_USER=\K.*' "$INSTALL_DIR/.env" 2>/dev/null || echo "medarch")
            DB_PASS=$(grep -oP 'DB_PASSWORD=\K.*' "$INSTALL_DIR/.env" 2>/dev/null || echo "")
            DB_NAME=$(grep -oP 'DB_NAME=\K.*' "$INSTALL_DIR/.env" 2>/dev/null || echo "medarch")

            if [ -n "$DB_PASS" ]; then
                gunzip -c "$LATEST_BACKUP/database.sql.gz" | mysql -u "$DB_USER" -p"$DB_PASS" "$DB_NAME"
            else
                gunzip -c "$LATEST_BACKUP/database.sql.gz" | mysql -u "$DB_USER" "$DB_NAME"
            fi
            echo -e "  ${GREEN}✓${NC} Datenbank wiederhergestellt"
        fi

        # Dateien wiederherstellen
        if [ -f "$LATEST_BACKUP/server-files.tar.gz" ]; then
            echo "Stelle Server-Dateien wieder her..."
            tar xzf "$LATEST_BACKUP/server-files.tar.gz" -C "$INSTALL_DIR/"
            echo -e "  ${GREEN}✓${NC} Dateien wiederhergestellt"
        fi

        # .env wiederherstellen
        if [ -f "$LATEST_BACKUP/.env.backup" ]; then
            cp "$LATEST_BACKUP/.env.backup" "$INSTALL_DIR/.env"
            chmod 600 "$INSTALL_DIR/.env"
            echo -e "  ${GREEN}✓${NC} Konfiguration wiederhergestellt"
        fi

        # Version zuruecksetzen
        if [ -f "$LATEST_BACKUP/.version-before" ]; then
            cp "$LATEST_BACKUP/.version-before" "$VERSION_FILE"
        fi

        echo "Starte Services..."
        systemctl daemon-reload
        for service in "${SERVICES[@]}"; do
            systemctl start "$service" 2>/dev/null && \
                echo -e "  ${GREEN}✓${NC} $service laeuft" || \
                echo -e "  ${RED}✗${NC} $service Fehler"
        done

        echo ""
        echo -e "${GREEN}Rollback abgeschlossen!${NC}"
        echo "  Version: $(get_version)"
        echo ""
        ;;

    deploy-log)
        if [ -f "$LOG_DIR/deploy.log" ]; then
            cat "$LOG_DIR/deploy.log"
        else
            echo "Kein Deploy-Log vorhanden."
        fi
        ;;

    autoupdate)
        RUNNER="python3 $INSTALL_DIR/update_runner.py"
        SUB="${2:-status}"
        case "$SUB" in
            status)   $RUNNER overview ;;
            on|auto)  require_root "autoupdate"; $RUNNER config --set mode=auto ;;
            off|manual) require_root "autoupdate"; $RUNNER config --set mode=manual ;;
            window)
                require_root "autoupdate"
                if [[ ! "$3" =~ ^[0-9]{1,2}:[0-9]{2}-[0-9]{1,2}:[0-9]{2}$ ]]; then
                    echo "Verwendung: medarch autoupdate window 02:00-03:30"; exit 1
                fi
                $RUNNER config --set "window_start=${3%-*}" --set "window_end=${3#*-}" ;;
            days)
                require_root "autoupdate"
                [ -z "$3" ] && { echo "Verwendung: medarch autoupdate days 0,1,2,3,4,5,6  (0=Mo ... 6=So)"; exit 1; }
                $RUNNER config --set "weekdays=$3" ;;
            security)
                require_root "autoupdate"
                [[ "$3" =~ ^(on|off)$ ]] || { echo "Verwendung: medarch autoupdate security on|off"; exit 1; }
                $RUNNER config --set "security_updates=$3" ;;
            set)      require_root "autoupdate"; shift 2; ARGS=(); for kv in "$@"; do ARGS+=(--set "$kv"); done; $RUNNER config "${ARGS[@]}" ;;
            mail)
                require_root "autoupdate"
                [ -z "$3" ] && { echo "Verwendung: medarch autoupdate mail it@praxis.de,chef@praxis.de  (- = Admins)"; exit 1; }
                if [ "$3" = "-" ]; then $RUNNER config --set "notify_emails=[]"; else $RUNNER config --set "notify_emails=$3"; fi ;;
            notify)
                require_root "autoupdate"
                [[ "$3" =~ ^(off|errors|updates|all)$ ]] || { echo "Verwendung: medarch autoupdate notify off|errors|updates|all"; exit 1; }
                $RUNNER config --set "notify_level=$3" ;;
            testmail) require_root "autoupdate"; $RUNNER testmail ;;
            check)    require_root "autoupdate"; $RUNNER check ;;
            history)  $RUNNER history ;;
            log)      journalctl -t medarch-update --no-hostname -n "${3:-100}" ;;
            unblock)  require_root "autoupdate"; $RUNNER unblock ;;
            *)
                echo "Verwendung: medarch autoupdate <befehl>"
                echo "  status                 Einstellungen, letzte Pruefung, naechstes Fenster"
                echo "  on | off               Automatisch installieren / nur pruefen (manuell)"
                echo "  window 02:00-03:30     Wartungsfenster setzen"
                echo "  days 0,1,2,3,4,5,6     Wochentage des Fensters (0=Mo ... 6=So)"
                echo "  security on|off        OS-Sicherheitsupdates mitinstallieren"
                echo "  mail a@x.de,b@y.de     Mail-Empfaenger (- = alle Admins)"
                echo "  notify off|errors|updates|all  Wann gemailt wird (Standard: errors)"
                echo "  testmail               Test-Benachrichtigung senden"
                echo "  set KEY=VALUE ...      Weitere Einstellungen (z. B. min_free_gb=3)"
                echo "  check                  Jetzt auf Updates pruefen"
                echo "  history                Verlauf der Update-Laeufe"
                echo "  log [n]                Journal des Update-Runners"
                echo "  unblock                Pausierte Auto-Updates wieder freigeben"
                exit 1 ;;
        esac
        ;;

    *)
        echo ""
        echo -e "${BOLD}MedArch Server - Verwaltung${NC}  ${DIM}v$(get_version)${NC}"
        echo ""
        echo "Verwendung: medarch <befehl>"
        echo ""
        echo -e "  ${BOLD}Service-Verwaltung:${NC}"
        echo "    status      Zeigt Status aller Services (mit RAM-Verbrauch)"
        echo "    start       Startet alle Services"
        echo "    stop        Stoppt alle Services"
        echo "    restart     Startet alle Services neu"
        echo "    logs        Zeigt Live-Logs (optional: medarch logs medarch-api)"
        echo ""
        echo -e "  ${BOLD}Updates & Deployment:${NC}"
        echo "    update      Lokales Update (Migration + Neustart)"
        echo "    upgrade     RPM-Update pruefen und installieren (mit Rollback)"
        echo "    autoupdate  Automatische Updates (status|on|off|window|days|history)"
        echo "    version     Zeigt Version und Update-Verfuegbarkeit"
        echo ""
        echo -e "  ${BOLD}Sicherheit:${NC}"
        echo "    backup      Erstellt Datenbank- und Datei-Backup"
        echo "    rollback    Stellt letztes Backup wieder her"
        echo "    health      Fuehrt vollstaendigen Health-Check durch"
        echo ""
        echo -e "  ${BOLD}Diagnose:${NC}"
        echo "    deploy-log  Zeigt Deployment-Historie"
        echo ""
        ;;
esac
