#!/usr/bin/env bash
# ============================================================
# Collecteur récursif de fichiers par extension
# Auteur : Quentin & GPT-5 (Lib-Lab)
# Fonction :
#   - Recherche récursivement un type de fichier donné (.yaml, .xml, .json, etc.)
#   - Copie ou déplace les fichiers vers un dossier cible
# ============================================================

set -euo pipefail

echo "=== Collecteur de fichiers récursif ==="
echo

# Parse minimal CLI options
DRY_RUN=false
if [[ "${1:-}" == "--dry-run" ]]; then
    DRY_RUN=true
    shift
fi

echo "=== Collecteur de fichiers récursif ==="
echo

# --- Demande à l'utilisateur les paramètres ---
read -rp "Dossier de recherche : " SRC_DIR
read -rp "Extensions à rechercher (ex: .yaml .yml .xml .json .conf) : " EXT_INPUT
read -rp "Dossier de destination : " DEST_DIR
read -rp "Déplacer au lieu de copier ? (y/n) : " MOVE_CHOICE

# --- Nettoyage et préparation ---
SRC_DIR="${SRC_DIR/#\~/$HOME}"
DEST_DIR="${DEST_DIR/#\~/$HOME}"

# Ne crée pas le dossier de destination en dry-run
if [[ "$DRY_RUN" == "false" ]]; then
    mkdir -p "$DEST_DIR"
else
    echo "[DRY-RUN] Le dossier de destination ne sera pas créé (dry-run) : $DEST_DIR"
fi

# --- Convertir extensions en tableau ---
IFS=' ' read -r -a EXT_LIST <<< "$EXT_INPUT"

# --- Compteur ---
COUNT=0

# --- Fonction pour copier ou déplacer un fichier ---
process_file() {
    local FILE="$1"
    local BASENAME
    BASENAME=$(basename "$FILE")
    local TARGET="$DEST_DIR/$BASENAME"

    # Évite d'écraser un fichier existant
    if [[ -e "$TARGET" ]]; then
        local i=1
        while [[ -e "$DEST_DIR/${BASENAME%.*}_$i.${BASENAME##*.}" ]]; do
            ((i++))
        done
        TARGET="$DEST_DIR/${BASENAME%.*}_$i.${BASENAME##*.}"
    fi

    if [[ "$MOVE_CHOICE" =~ ^[Yy]$ ]]; then
        if [[ "$DRY_RUN" == "true" ]]; then
            echo "  [DRY-RUN] Déplacé : $FILE → $TARGET"
        else
            mv "$FILE" "$TARGET"
            echo "  Déplacé : $FILE → $TARGET"
        fi
    else
        if [[ "$DRY_RUN" == "true" ]]; then
            echo "  [DRY-RUN] Copié   : $FILE → $TARGET"
        else
            cp -a "$FILE" "$TARGET"
            echo "  Copié   : $FILE → $TARGET"
        fi
    fi
    ((COUNT++))
}

# --- Recherche récursive (robuste, supporte noms avec espaces) ---
echo
echo "[+] Recherche de fichiers dans : $SRC_DIR"

# Empêche que le dossier de destination soit parcouru (évite récopie infinie)
EXCLUDE_PRUNE=""
if [[ -n "$DEST_DIR" ]]; then
    # make sure absolute paths for comparison
    SRC_DIR_ABS=$(cd "$SRC_DIR" && pwd)
    DEST_DIR_ABS=$(cd "$DEST_DIR" && pwd)
    if [[ "$DEST_DIR_ABS" == "$SRC_DIR_ABS"* ]]; then
        echo "[!] Attention : le dossier de destination est dans l'arborescence source. Le dossier destination sera exclu du scan."
        EXCLUDE_PRUNE="-path '$DEST_DIR_ABS' -prune -o"
    fi
fi

for EXT in "${EXT_LIST[@]}"; do
    # normalize extension (accepts 'yaml' or '.yaml')
    ext_trimmed=$(echo "$EXT" | xargs)
    if [[ -z "$ext_trimmed" ]]; then
        continue
    fi
    # build a case-insensitive pattern like '*.yaml'
    if [[ "$ext_trimmed" == .* ]]; then
        pattern="*${ext_trimmed}"
    else
        pattern="*.${ext_trimmed}"
    fi

    echo "    - Extension : $EXT (pattern: $pattern)"

    # build find command safely as array to handle spaces in paths
    find_cmd=(find "$SRC_DIR")
    if [[ -n "$EXCLUDE_PRUNE" ]]; then
        # append the prune expression using the absolute dest dir
        find_cmd+=( -path "$DEST_DIR_ABS" -prune -o )
    fi
    find_cmd+=( -type f -iname "$pattern" -print0 )

    # Collect results into an array first so we can report count (handles null-delimited names)
    matches=()
    while IFS= read -r -d '' FILE; do
        matches+=("$FILE")
    done < <("${find_cmd[@]}")

    echo "      -> Fichiers trouvés: ${#matches[@]}"
    if [[ ${#matches[@]} -eq 0 ]]; then
        continue
    fi

    # Affiche les premiers items pour debug quand il y a beaucoup de résultats
    if [[ ${#matches[@]} -gt 0 ]]; then
        echo "      -> Exemples (10 premiers) :"
        local j=0
        for sample in "${matches[@]}"; do
            echo "         - $sample"
            ((j++)) || true
            [[ $j -ge 10 ]] && break
        done
    fi

    total_matches=${#matches[@]}
    idx=0
    for FILE in "${matches[@]}"; do
        ((idx++)) || true
        if [[ "$DRY_RUN" == "true" ]]; then
            echo "      [${idx}/${total_matches}] -> $FILE"
        fi
        # ignore si le fichier est dans le dossier de destination (sécurité)
        case "${FILE}" in
            "$DEST_DIR_ABS"/*) continue ;;
        esac
        process_file "$FILE"
    done
done

echo
echo "[✓] Total : $COUNT fichiers traités."
echo "Résultats enregistrés dans : $DEST_DIR"
echo "============================================================"
