#!/bin/bash
#
# S2 Checkliste - Deployment Script
# Installiert das System auf Debian/Ubuntu mit Apache (Port 80 oder vorhanden).
#
# Usage:
#   sudo bash install.sh                    # Normal installieren
#   sudo bash install.sh --debug            # Mit Debug-Ausgaben
#   sudo DEBUG=1 bash install.sh            # Mit Debug-Ausgaben (via Env)
#   sudo bash install.sh --uninstall        # Deinstallieren
#   sudo bash install.sh --force            # Ohne Nachfrage neu installieren
#
# WICHTIG: Caddy wird NIEMALS gestoppt oder deaktiviert.

# Pufferung deaktivieren
exec 2>&1

# Debug-Modus aktivieren wenn --debug oder DEBUG=1
DEBUG=0
if [[ "${1:-}" == "--debug" || "${1:-}" == "--trace" || "${DEBUG:-0}" == "1" ]]; then
    DEBUG=1
    export PS4='+${LINENO}: '
    if [[ "${1:-}" == "--trace" ]]; then
        set -x
    fi
    shift 2>/dev/null || true
fi

set -eo pipefail

# =============================================================================
# KONFIGURATION - ANPASSBAR DURCH UMGEBUNGSVARIABLEN
# =============================================================================

APP_NAME="${APP_NAME:-S2 Checkliste}"
APP_DIR="${APP_DIR:-/var/www/devbox.s2-it.de/check}"
APP_URL="${APP_URL:-https://devbox.s2-it.de/checkliste/}"
DB_NAME="${DB_NAME:-s2_checkliste}"
DB_USER="${DB_USER:-s2_checkliste_user}"
ADMIN_EMAIL="${ADMIN_EMAIL:-admin}"
ADMIN_PASS="${ADMIN_PASS:-Admin1234!}"
APACHE_SITE="${APACHE_SITE:-devbox-checkliste}"
CRON_FILE="${CRON_FILE:-/etc/cron.d/s2-checkliste}"
CRON_LOG="${CRON_LOG:-/var/log/s2-checkliste-cron.log}"
SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CREDENTIALS_FILE="${CREDENTIALS_FILE:-/root/s2-checkliste-credentials.txt}"
INSTALL_MODE="${INSTALL_MODE:-auto}"

# Farbcodes
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly CYAN='\033[0;36m'
readonly NC='\033[0m'

# Log-Datei
LOG_FILE="/tmp/s2-checkliste-install-$(date +%Y%m%d-%H%M%S).log"
exec > >(tee -a "$LOG_FILE")
exec 2>&1

# =============================================================================
# HILFSFUNKTIONEN
# =============================================================================

debug() {
    if [[ $DEBUG -eq 1 ]]; then
        echo -e "${CYAN}[DEBUG $(date '+%H:%M:%S')]${NC} $1"
    fi
}

info() { 
    echo -e "${BLUE}[INFO]${NC} $1" 
    debug "$1"
}

success() { 
    echo -e "${GREEN}[OK]${NC} $1"
    debug "SUCCESS: $1"
}

warn() { 
    echo -e "${YELLOW}[WARN]${NC} $1" 
    debug "WARN: $1"
}

error() { 
    echo -e "${RED}[ERROR]${NC} $1" 
    debug "ERROR: $1"
}

step() { 
    echo ""
    echo -e "${BLUE}==>${NC} $1" 
    echo "========================================"
}

generate_password() { 
    openssl rand -base64 24 | tr -d "=+/" | cut -c1-20 
}

check_root() { 
    if [[ $EUID -ne 0 ]]; then 
        error "Dieses Script muss als root ausgeführt werden"
        exit 1 
    fi 
}

check_apt_locks() {
    debug "Prüfe auf apt/dpkg Locks..."
    local locked=0
    
    for lock in "/var/lib/dpkg/lock-frontend" "/var/lib/apt/lists/lock"; do
        if [[ -f "$lock" ]] && fuser "$lock" >/dev/null 2>&1; then
            warn "Lock aktiv: $lock"
            locked=1
        fi
    done
    
    if [[ $locked -eq 1 ]]; then
        warn "Warte auf Paketmanager..."
        for i in 10 9 8 7 6 5 4 3 2 1; do
            if ! fuser "/var/lib/dpkg/lock-frontend" >/dev/null 2>&1; then
                success "Paketmanager frei"
                return 0
            fi
            sleep 1
        done
        error "Paketmanager immer noch beschäftigt"
        exit 1
    fi
}

detect_php_version() {
    if command -v php &>/dev/null; then
        php -r "echo 'php' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION;"
    else
        echo "php8.2"
    fi
}

detect_existing_installation() {
    local exists=false
    [[ -d "$APP_DIR" ]] && exists=true
    [[ -f "/etc/apache2/sites-available/${APACHE_SITE}.conf" ]] && exists=true
    mysql -e "USE ${DB_NAME};" 2>/dev/null && exists=true
    [[ -f "$CRON_FILE" ]] && exists=true
    echo "$exists"
}

# =============================================================================
# DEINSTALLATION
# =============================================================================

uninstall_app() {
    local force="${1:-false}"
    step "Deinstallation von ${APP_NAME}"

    if [[ "$force" != true ]]; then
        echo ""
        warn "WARNUNG: Dies löscht ALLE Daten unwiderruflich!"
        read -r -p "Wirklich deinstallieren? [j/N]: " REPLY
        echo ""
        if [[ ! "$REPLY" =~ ^[Jj]$ ]]; then
            info "Abbruch."
            exit 0
        fi
    fi

    if [[ -f "/etc/apache2/sites-available/${APACHE_SITE}.conf" ]]; then
        info "Deaktiviere Apache-Site..."
        a2dissite "${APACHE_SITE}.conf" 2>/dev/null || true
        rm -f "/etc/apache2/sites-available/${APACHE_SITE}.conf"
        success "Apache-Site entfernt"
        systemctl reload apache2 2>/dev/null || true
    fi

    if [[ -d "$APP_DIR" ]]; then
        info "Lösche App-Verzeichnis ${APP_DIR}..."
        rm -rf "$APP_DIR"
        success "App-Verzeichnis gelöscht"
    fi

    if mysql -e "USE ${DB_NAME};" 2>/dev/null; then
        info "Lösche Datenbank ${DB_NAME}..."
        mysql -e "DROP DATABASE IF EXISTS \`${DB_NAME}\`;" 2>/dev/null || true
        mysql -e "DROP USER IF EXISTS '${DB_USER}'@'localhost';" 2>/dev/null || true
        success "Datenbank gelöscht"
    fi

    if [[ -f "$CRON_FILE" ]]; then
        rm -f "$CRON_FILE"
        success "Cronjob entfernt"
    fi

    if [[ -f "$CREDENTIALS_FILE" ]]; then
        rm -f "$CREDENTIALS_FILE"
        success "Credentials-Datei gelöscht"
    fi

    success "Deinstallation abgeschlossen"
}

# =============================================================================
# INSTALLATION: EINZELNE SCHRITTE
# =============================================================================

check_and_install_packages() {
    step "Prüfe Systemvoraussetzungen"
    debug "APP_DIR=$APP_DIR, DB_NAME=$DB_NAME"

    info "Prüfe vorhandene Komponenten..."

    # Apache
    debug "Prüfe Apache..."
    if command -v apache2 &>/dev/null && systemctl is-active apache2 &>/dev/null; then
        success "Apache bereits installiert und läuft"
    else
        check_apt_locks
        warn "Apache nicht gefunden"
        info "Installiere Apache..."
        apt-get update -qq
        apt-get install -y -qq apache2
        systemctl enable apache2 2>/dev/null || true
        success "Apache installiert"
    fi

    # MariaDB
    debug "Prüfe MariaDB..."
    if command -v mysql &>/dev/null; then
        success "MariaDB/MySQL bereits installiert"
    else
        check_apt_locks
        warn "MariaDB nicht gefunden"
        info "Installiere MariaDB..."
        apt-get install -y -qq mariadb-server mariadb-client
        systemctl enable mariadb 2>/dev/null || true
        success "MariaDB installiert"
    fi

    # PHP und Erweiterungen
    debug "Prüfe PHP..."
    if command -v php &>/dev/null; then
        local php_version
        php_version=$(php -r "echo 'php' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION;")
        local php_full_version
        php_full_version=$(php -r "echo PHP_VERSION;")
        success "PHP gefunden: ${php_full_version}"
        info "Verwende PHP-Version: ${php_version}"
        debug "PHP OK"
    else
        error "PHP nicht gefunden"
        exit 1
    fi

    # Tools
    debug "Prüfe Tools..."
    local tools=("unzip" "curl" "rsync" "openssl")
    local missing_tools=()
    for tool in "${tools[@]}"; do
        if ! command -v "$tool" &>/dev/null; then
            missing_tools+=("$tool")
            debug "Tool fehlt: $tool"
        fi
    done

    if [[ ${#missing_tools[@]} -gt 0 ]]; then
        check_apt_locks
        info "Installiere Tools: ${missing_tools[*]}"
        apt-get install -y -qq "${missing_tools[@]}"
        success "Tools installiert"
    else
        info "Alle Tools vorhanden"
    fi

    # Composer
    debug "Prüfe Composer..."
    if ! command -v composer &>/dev/null; then
        info "Installiere Composer..."
        curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
        success "Composer installiert"
    else
        info "Composer bereits installiert"
    fi
    debug "Composer-Prüfung abgeschlossen"
}

configure_apache() {
    step "Konfiguriere Apache für ${APP_DIR}"
    debug "Konfiguriere Apache..."

    info "Aktiviere Apache-Module..."
    a2enmod rewrite >/dev/null 2>&1 || true
    a2enmod headers >/dev/null 2>&1 || true
    success "Apache-Module aktiviert"

    info "Schreibe VirtualHost-Konfiguration..."
    
    cat > "/etc/apache2/sites-available/${APACHE_SITE}.conf" << APACHEEOF
Alias /checkliste ${APP_DIR}/public
Alias /checkliste/ ${APP_DIR}/public/

<Directory ${APP_DIR}/public>
    Options -Indexes +FollowSymLinks
    AllowOverride All
    Require all granted
    Header always set X-Frame-Options "SAMEORIGIN"
</Directory>

php_value upload_max_filesize 10M
php_value memory_limit 256M

ErrorLog \${APACHE_LOG_DIR}/s2_checkliste_error.log
CustomLog \${APACHE_LOG_DIR}/s2_checkliste_access.log combined
APACHEEOF

    debug "Apache-Konfiguration geschrieben"

    a2ensite "${APACHE_SITE}.conf" >/dev/null 2>&1
    success "Apache Konfiguration aktiviert"
}

deploy_application() {
    step "Deploye Anwendung nach ${APP_DIR}"
    debug "Kopiere Dateien..."

    mkdir -p "$APP_DIR"
    rsync -a --exclude='.git' --exclude='vendor' --exclude='install.sh' \
        "${SOURCE_DIR}/" "${APP_DIR}/"
    
    success "Dateien kopiert"
}

install_composer_deps() {
    step "Installiere Composer-Abhängigkeiten"
    debug "Wechsle zu $APP_DIR"

    cd "$APP_DIR"

    if [[ ! -f "composer.json" ]]; then
        error "composer.json nicht gefunden"
        exit 1
    fi

    if ! curl -s --max-time 10 https://repo.packagist.org/ >/dev/null 2>&1; then
        warn "Keine Internetverbindung zu Packagist"
        warn "Führen Sie später aus: cd ${APP_DIR} && composer install"
        return 0
    fi

    info "Installiere Composer-Pakete..."
    composer install --no-dev --optimize-autoloader --no-interaction 2>&1
    success "Composer-Abhängigkeiten installiert"
}

setup_database() {
    step "Richte Datenbank ein"
    debug "Setup Datenbank..."

    if ! systemctl is-active mariadb >/dev/null 2>&1; then
        info "Starte MariaDB..."
        systemctl start mariadb
    fi

    # Passwort generieren
    if [[ -z "${DB_PASS:-}" ]]; then
        DB_PASS="$(generate_password)"
    fi
    debug "DB_PASS=****"

    info "Erstelle Datenbank..."
    mysql -e "CREATE DATABASE IF NOT EXISTS \`${DB_NAME}\` CHARACTER SET utf8mb4;" 2>/dev/null
    mysql -e "CREATE USER IF NOT EXISTS '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASS}';" 2>/dev/null || true
    mysql -e "GRANT ALL PRIVILEGES ON \`${DB_NAME}\`.* TO '${DB_USER}'@'localhost';" 2>/dev/null
    mysql -e "FLUSH PRIVILEGES;" 2>/dev/null
    success "Datenbank angelegt"

    # Schema importieren
    local schema_file="${APP_DIR}/database/schema.sql"
    if [[ -f "$schema_file" ]]; then
        info "Importiere Schema..."
        mysql "$DB_NAME" < "$schema_file"
        success "Schema importiert"
    fi

    # DSEV-Migration
    local dsev_migration="${APP_DIR}/database/migrations/001_add_dsev_fields.sql"
    if [[ -f "$dsev_migration" ]]; then
        info "Führe DSEV-Migration aus..."
        mysql "$DB_NAME" < "$dsev_migration" 2>/dev/null || true
        success "DSEV-Migration ausgeführt"
    fi

    # Admin anlegen
    info "Erstelle Admin-Benutzer..."
    local admin_hash
    admin_hash=$(php -r "echo password_hash('${ADMIN_PASS}', PASSWORD_DEFAULT);")
    
    mysql "$DB_NAME" -e "
        INSERT INTO users (email, password_hash, first_name, last_name, role, is_active, created_at)
        VALUES ('${ADMIN_EMAIL}', '${admin_hash}', 'Admin', 'Benutzer', 'admin', 1, NOW())
        ON DUPLICATE KEY UPDATE password_hash = '${admin_hash}', role = 'admin', is_active = 1;
    " 2>/dev/null
    success "Admin angelegt"
}

create_env() {
    step "Erstelle .env-Datei"

    cat > "${APP_DIR}/.env" << EOF
APP_NAME="S2 Checkliste"
APP_URL=${APP_URL}
APP_ENV=production
APP_DEBUG=false
APP_INSTALLED=true

DB_HOST=localhost
DB_PORT=3306
DB_NAME=${DB_NAME}
DB_USER=${DB_USER}
DB_PASS=${DB_PASS}
DB_CHARSET=utf8mb4

SMTP_HOST=
SMTP_PORT=587
SMTP_USER=
SMTP_PASS=
SMTP_ENCRYPTION=tls
SMTP_FROM_NAME="S2 Checkliste"
SMTP_FROM_EMAIL=

SESSION_NAME=S2Checkliste
SESSION_LIFETIME=3600

HR_EMAIL=

DSEV_ENABLED=false
DSEV_BASE_URL=https://portal.dsev.online/api
DSEV_COMPANY_ID=4452
DSEV_API_TOKEN=
DSEV_DEFAULT_LANG=DE
EOF

    chmod 640 "${APP_DIR}/.env"
    chown root:www-data "${APP_DIR}/.env" 2>/dev/null || true
    success ".env erstellt"
}

set_permissions() {
    step "Setze Berechtigungen"

    mkdir -p "${APP_DIR}/storage/documents"
    mkdir -p "${APP_DIR}/storage/logs"

    chown -R www-data:www-data "$APP_DIR"
    chmod 755 "${APP_DIR}/storage"
    chmod 755 "${APP_DIR}/storage/documents"
    chmod 755 "${APP_DIR}/storage/logs"
    chmod 640 "${APP_DIR}/.env"

    success "Berechtigungen gesetzt"
}

setup_cron() {
    step "Richte Cronjob ein"

    touch "$CRON_LOG"
    chown www-data:www-data "$CRON_LOG"

    cat > "$CRON_FILE" << CRONEOF
*/5 * * * * www-data php ${APP_DIR}/cron/send_due_mails.php >> ${CRON_LOG} 2>&1
CRONEOF

    chmod 644 "$CRON_FILE"
    success "Cronjob gesetzt"
}

restart_apache() {
    step "Starte Apache neu"

    if apache2ctl configtest 2>&1 | grep -q "Syntax OK"; then
        success "Apache-Konfiguration OK"
    else
        warn "Apache-Konfiguration hat Warnungen"
    fi

    systemctl reload apache2 || systemctl restart apache2
    success "Apache neu gestartet"
}

save_credentials() {
    local ip_address
    ip_address=$(hostname -I | awk '{print $1}' || echo "?")

    cat > "$CREDENTIALS_FILE" << EOF
${APP_NAME} - Zugangsdaten

URL: ${APP_URL}
Intern: http://${ip_address}/checkliste/

Datenbank:
  Name: ${DB_NAME}
  User: ${DB_USER}
  Pass: ${DB_PASS}

Admin:
  User: ${ADMIN_EMAIL}
  Pass: ${ADMIN_PASS}

Log: ${LOG_FILE}
EOF

    chmod 600 "$CREDENTIALS_FILE"
    success "Zugangsdaten gespeichert: ${CREDENTIALS_FILE}"
}

show_summary() {
    echo ""
    echo "=========================================="
    echo " ${APP_NAME} - Installation abgeschlossen"
    echo "=========================================="
    echo ""
    echo " URL: ${APP_URL}"
    echo ""
    echo " Admin: ${ADMIN_EMAIL}"
    echo " Pass:  ${ADMIN_PASS}"
    echo ""
    echo " Log: ${LOG_FILE}"
    echo "=========================================="
}

# =============================================================================
# HAUPTPROGRAMM
# =============================================================================

main() {
    check_root

    local UNINSTALL=false
    local FORCE=false

    while [[ $# -gt 0 ]]; do
        case "$1" in
            -u|--uninstall) UNINSTALL=true; shift ;;
            --force) FORCE=true; shift ;;
            -h|--help) 
                echo "Verwendung: sudo bash $0 [OPTION]"
                echo ""
                echo "Optionen:"
                echo "  --debug       Mit Debug-Ausgaben"
                echo "  --trace       Mit Trace-Modus"
                echo "  --uninstall   Deinstallieren"
                echo "  --force       Ohne Nachfrage"
                echo "  --help        Hilfe"
                exit 0
                ;;
            *) error "Unbekannte Option: $1"; exit 1 ;;
        esac
    done

    if [[ "$UNINSTALL" == true ]]; then
        uninstall_app "$FORCE"
        exit 0
    fi

    if [[ "$(detect_existing_installation)" == "true" ]]; then
        if [[ "$FORCE" == true ]]; then
            uninstall_app true
        else
            echo ""
            warn "Bestehende Installation erkannt!"
            echo ""
            echo "[j] Neu installieren"
            echo "[d] Deinstallieren"
            echo "[n] Abbrechen"
            echo ""
            read -r -p "Wahl [j/d/n]: " REPLY
            echo ""
            case "$REPLY" in
                [Jj]) uninstall_app true ;;
                [Dd]) uninstall_app true; exit 0 ;;
                *) info "Abbruch."; exit 0 ;;
            esac
        fi
    fi

    step "Starte Installation von ${APP_NAME}"
    debug "APP_DIR=$APP_DIR"
    debug "APP_URL=$APP_URL"

    check_and_install_packages
    configure_apache
    deploy_application
    install_composer_deps
    setup_database
    create_env
    set_permissions
    setup_cron
    restart_apache
    save_credentials
    show_summary

    success "Installation abgeschlossen!"
}

main "$@"
