#!/bin/bash
set -eo pipefail

# Configuration
ROOT_DIR=$(git rev-parse --show-toplevel)
CLANG_FORMAT_BIN="${ROOT_DIR}/.tools/clang-format"
CLANG_CONFIG="${ROOT_DIR}/.tools/.clang-format"
TARGET_DIRS=("Source" "Private" "Public" "Classes")
FILE_EXTS=("*.h" "*.cpp" "*.hpp" "*.c")

# Options
DRY_RUN=false
VERBOSE=false
CHECK_MODIFIED=false

# Help text
show_help() {
    cat <<EOF
Usage: $0 [OPTIONS]

Options:
  --dry-run       Check formatting without modifying files
  --verbose       Show detailed processing information
  --modified-only Check only modified files
  --help          Show this help message

Exit codes:
  0 - Everything formatted correctly
  1 - Formatting errors detected
  2 - Configuration error
EOF
}

# Parse arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        --dry-run)      DRY_RUN=true; shift ;;
        --verbose)      VERBOSE=true; shift ;;
        --modified-only) CHECK_MODIFIED=true; shift ;;
        --help)         show_help; exit 0 ;;
        *)              echo "Unknown option: $1"; exit 2 ;;
    esac
done

# Verify dependencies
check_dependencies() {
    if [[ ! -x "${CLANG_FORMAT_BIN}" ]]; then
        echo "❌ clang-format non trouvé ou non exécutable dans .tools/"
        echo "   Vérifiez le chemin: ${CLANG_FORMAT_BIN}"
        exit 2
    fi
    
    if [[ ! -f "${CLANG_CONFIG}" ]]; then
        echo "❌ Fichier de configuration .clang-format manquant"
        echo "   Vérifiez le chemin: ${CLANG_CONFIG}"
        exit 2
    fi
}

# File discovery
find_source_files() {
    local files=()
    
    if [[ "${CHECK_MODIFIED}" == true ]]; then
        # Fichiers modifiés uniquement
        mapfile -t files < <(git diff --name-only --diff-filter=ACMR HEAD -- $(printf "%s " "${TARGET_DIRS[@]}") | grep -E '\.(h|cpp|hpp|c)$')
    else
        # Tous les fichiers
        for dir in "${TARGET_DIRS[@]}"; do
            local full_dir="${ROOT_DIR}/${dir}"
            if [[ -d "${full_dir}" ]]; then
                while IFS= read -r -d '' file; do
                    files+=("$file")
                done < <(find "${full_dir}" -type f \( \
                    -name "*.h" -o \
                    -name "*.cpp" -o \
                    -name "*.hpp" -o \
                    -name "*.c" \) -print0)
            fi
        done
    fi

    printf "%s\n" "${files[@]}"
}


# Main process
main() {
    check_dependencies

    local files
    mapfile -t files < <(find_source_files)

	if [[ ${#files[@]} -eq 0 ]]; then
		${VERBOSE} && echo "ℹ️ Aucun fichier trouvé dans ${TARGET_DIRS[*]}"
		return
	fi

    ${VERBOSE} && echo "📁 Fichiers à vérifier : ${#files[@]}"

    local format_args=("-style=file" "${CLANG_CONFIG}")
    local errors=0

    if [[ "${DRY_RUN}" == true ]]; then
        format_args+=(--dry-run --Werror)
        ${VERBOSE} && echo "🔍 Mode vérification seulement"
    else
        format_args+=(-i)
        ${VERBOSE} && echo "🛠️  Application du formatage"
    fi

    for file in "${files[@]}"; do
        ${VERBOSE} && echo "🔎 Traitement : ${file}"
        
        if ! "${CLANG_FORMAT_BIN}" "${format_args[@]}" "${file}"; then
            ((errors++))
            ${DRY_RUN} && echo "❌ Problème détecté : ${file}"
        fi
    done

    if [[ ${errors} -gt 0 ]]; then
        echo -e "\n❌ ${errors} fichier(s) nécessitent un formatage"
        exit 1
    else
        echo -e "\n✅ Tous les fichiers sont correctement formatés !"
        exit 0
    fi
}

# Execution
main