#!/usr/bin/env bash
#
# Surveillance d'intégrité WordPress par baseline (empreintes MD5 + mtime).
# À exécuter sur le serveur depuis la racine WordPress (ou avec WP_ROOT défini).
#
# Usage:
#   ./surveillance-wp.sh baseline [--full]   # Créer la baseline (une fois après nettoyage)
#   ./surveillance-wp.sh check               # Comparer à la baseline, générer rapport
#
# Baseline stockée dans WP_ROOT/.malware-scripts/baseline/
# Rapports dans WP_ROOT/wp-surveillance/
#

set -e

WP_ROOT="${WP_ROOT:-/home/eglisebaa/www}"
BASELINE_DIR="${WP_ROOT}/.malware-scripts/baseline"
REPORT_DIR="${WP_ROOT}/wp-surveillance"
REPORT_FILE=""
CHANGES=0

cd "$WP_ROOT"
if [ ! -f "wp-includes/version.php" ]; then
    echo "Erreur : racine WordPress introuvable (wp-includes/version.php). Définir WP_ROOT si besoin."
    exit 1
fi

mkdir -p "$BASELINE_DIR"
mkdir -p "$REPORT_DIR"

# Séparateur dans les fichiers baseline : chemin|md5|mtime (relatif à WP_ROOT)
_line_hash() {
    local f="$1"
    local rel="${f#./}"
    if [ ! -f "$f" ]; then
        return 1
    fi
    if [ -r "$f" ]; then
        local h
        local m
        h=$(md5sum "$f" 2>/dev/null | awk '{print $1}' || md5 -q "$f" 2>/dev/null)
        m=$(stat -c %Y "$f" 2>/dev/null || stat -f %m "$f" 2>/dev/null)
        echo "${rel}|${h}|${m}"
    fi
}

# ----- baseline -----
cmd_baseline() {
    local full=0
    [ "$1" = "--full" ] && full=1

    echo "Création de la baseline (WP_ROOT=$WP_ROOT)"
    echo "  - Core + racine"
    > "$BASELINE_DIR/baseline-core.txt"
    local core_files="index.php wp-blog-header.php wp-load.php wp-settings.php .htaccess wp-login.php wp-config.php"
    for f in $core_files; do
        if [ -f "$f" ]; then
            _line_hash "$f" >> "$BASELINE_DIR/baseline-core.txt"
        fi
    done
    while IFS= read -r -d '' f; do
        [ -f "$f" ] && _line_hash "$f" >> "$BASELINE_DIR/baseline-core.txt"
    done < <(find . -maxdepth 1 -type f -name "*.php" -print0 2>/dev/null)
    sort -u "$BASELINE_DIR/baseline-core.txt" -o "$BASELINE_DIR/baseline-core.txt"

    echo "  - wp-content/uploads"
    > "$BASELINE_DIR/baseline-uploads.txt"
    if [ -d "wp-content/uploads" ]; then
        while IFS= read -r -d '' f; do
            _line_hash "$f" >> "$BASELINE_DIR/baseline-uploads.txt"
        done < <(find wp-content/uploads -type f -print0 2>/dev/null)
        sort -u "$BASELINE_DIR/baseline-uploads.txt" -o "$BASELINE_DIR/baseline-uploads.txt"
    fi

    if [ "$full" -eq 1 ]; then
        echo "  - wp-content/plugins et themes (--full)"
        > "$BASELINE_DIR/baseline-full.txt"
        for dir in wp-content/plugins wp-content/themes; do
            [ ! -d "$dir" ] && continue
            while IFS= read -r -d '' f; do
                _line_hash "$f" >> "$BASELINE_DIR/baseline-full.txt"
            done < <(find "$dir" -type f -name "*.php" -print0 2>/dev/null)
        done
        sort -u "$BASELINE_DIR/baseline-full.txt" -o "$BASELINE_DIR/baseline-full.txt"
    else
        rm -f "$BASELINE_DIR/baseline-full.txt"
    fi

    echo "Baseline enregistrée dans $BASELINE_DIR"
}

# ----- check : compare et rapport -----
_report() {
    echo "$1" >> "$REPORT_FILE"
}

_check_file() {
    local path="$1"
    local old_md5="$2"
    local old_mtime="$3"
    if [ ! -f "$WP_ROOT/$path" ]; then
        _report "  SUPPRIMÉ: $path"
        CHANGES=1
        return
    fi
    local new_hash new_mtime
    new_hash=$(md5sum "$WP_ROOT/$path" 2>/dev/null | awk '{print $1}' || md5 -q "$WP_ROOT/$path" 2>/dev/null)
    new_mtime=$(stat -c %Y "$WP_ROOT/$path" 2>/dev/null || stat -f %m "$WP_ROOT/$path" 2>/dev/null)
    if [ "$new_hash" != "$old_md5" ] || [ "$new_mtime" != "$old_mtime" ]; then
        _report "  MODIFIÉ: $path (ancien md5=$old_md5, nouveau=$new_hash)"
        CHANGES=1
    fi
}

_check_baseline_file() {
    local file="$1"
    local name="$2"
    [ ! -f "$file" ] && return
    _report ""
    _report "--- $name ---"
    while IFS='|' read -r path old_md5 old_mtime; do
        [ -z "$path" ] && continue
        _check_file "$path" "$old_md5" "$old_mtime"
    done < "$file"
}

_check_added_uploads() {
    [ ! -f "$BASELINE_DIR/baseline-uploads.txt" ] && return
    local in_baseline
    in_baseline=$(mktemp)
    cut -d'|' -f1 "$BASELINE_DIR/baseline-uploads.txt" | sort -u > "$in_baseline"
    _report ""
    _report "--- Fichiers ajoutés (uploads) ---"
    find wp-content/uploads -type f 2>/dev/null | sort | while read -r f; do
        if ! grep -qFx "$f" "$in_baseline"; then
            _report "  AJOUTÉ: $f"
            CHANGES=1
        fi
    done
    rm -f "$in_baseline"
}

_check_added_root_php() {
    _report ""
    _report "--- Fichiers PHP ajoutés (racine) ---"
    local in_baseline
    in_baseline=$(mktemp)
    cut -d'|' -f1 "$BASELINE_DIR/baseline-core.txt" | sort -u > "$in_baseline"
    find . -maxdepth 1 -type f -name "*.php" 2>/dev/null | sed 's|^\./||' | sort -u | while read -r f; do
        if ! grep -qFx "$f" "$in_baseline"; then
            _report "  AJOUTÉ: $f"
            CHANGES=1
        fi
    done
    rm -f "$in_baseline"
}

cmd_check() {
    if [ ! -f "$BASELINE_DIR/baseline-core.txt" ]; then
        echo "Erreur : aucune baseline trouvée. Exécutez d'abord : $0 baseline"
        exit 1
    fi

    REPORT_FILE="$REPORT_DIR/wp-surveillance-$(date +%Y%m%d-%H%M%S).txt"
    CHANGES=0

    {
        echo "Rapport de surveillance WordPress"
        echo "Date: $(date)"
        echo "WP_ROOT: $WP_ROOT"
        echo "Comparaison à la baseline dans $BASELINE_DIR"
    } > "$REPORT_FILE"

    _check_baseline_file "$BASELINE_DIR/baseline-core.txt" "Core et racine"
    _check_added_root_php
    _check_baseline_file "$BASELINE_DIR/baseline-uploads.txt" "wp-content/uploads"
    _check_added_uploads

    if [ -f "$BASELINE_DIR/baseline-full.txt" ]; then
        _check_baseline_file "$BASELINE_DIR/baseline-full.txt" "Plugins et thèmes (--full)"
    fi

    # Recompter les changements (certains sont détectés dans des sous-shells)
    if grep -qE 'MODIFIÉ|SUPPRIMÉ|AJOUTÉ' "$REPORT_FILE" 2>/dev/null; then
        CHANGES=1
    fi

    if [ $CHANGES -eq 0 ]; then
        _report ""
        _report "Aucun changement détecté."
        echo "Aucun changement. Rapport: $REPORT_FILE"
        exit 0
    fi

    _report ""
    _report "--- Fin du rapport ---"
    echo "Changements détectés. Rapport: $REPORT_FILE"
    cat "$REPORT_FILE"
    exit 1
}

# ----- main -----
case "${1:-}" in
    baseline)
        cmd_baseline "${2:-}"
        ;;
    check)
        cmd_check
        ;;
    *)
        echo "Usage: $0 baseline [--full] | check"
        echo "  baseline     Créer la baseline (après nettoyage / restauration backup)"
        echo "  baseline --full  Inclure plugins et thèmes"
        echo "  check        Comparer à la baseline et générer un rapport"
        exit 1
        ;;
esac
