#!/bin/bash
# ==============================================================================
# COMPREHENSIVE FILE RENAMING TOOL WITH INTERACTIVE MENU
# ==============================================================================
# Features:
# 1. Interactive CLI Menu
# 2. Verbose Mode (-v, --verbose)
# 3. Dry-Run/Test Mode (-t, --test, --dry-run)
# 4. Selective actions: -a (all), -d (dirs), -n (names/files), -c (content)
# 5. Recursive Renaming (Dirs & Files)
# 6. Content Reference Updating (filename strings only)
# 7. Summary report + check/preview mode
# ==============================================================================
# FILESYSTEM NAMING RULES (rename only):
# - Both files and directories MUST be lowercase
# - Directories: cannot contain '.', '-', or spaces → replace with '_'
#               ('_' is allowed)
# - Files:      cannot contain '-', '_', or spaces → replace with '.'
#
# CONTENT UPDATE RULES (what gets changed inside text files):
# - ONLY strings that appear in known filename-reference *contexts* for the
#   file type are candidates for replacement.
# - Patterns by type:
#     .php  → include / require (+ __DIR__ concatenations) + HTML attrs
#     .html → <script src>, <link href>, <img src>, ...
#     .js   → import / require / from
#     .css  → @import and url()
#     .sh   → source / . / ./file
# - Ordinary variables or plain text are never touched.
# - Example changed:  include "rick_seg1_seg.php"  →  include "rick.seg1.seg.php"
# - Example NOT changed:  $my_var_name  or  some_text_with_underscores
# ==============================================================================

# --- Global Configuration ---
VERBOSE=false
DRY_RUN=false
EXCLUDE_PATHS=(
    "*/.git/*"
    "*/node_modules/*"
    "*/backup/*"
    "*/.cache/*"
    "*/.DS_Store"
    "*/file_manager_cli.sh"
    "*/setup_test_env.sh"
)

# Action flags (CLI)
DO_DIRS=false
DO_FILES=false
DO_CONTENT=false
DO_ALL=false

# Counters for summary
RENAME_DIR_COUNT=0
RENAME_FILE_COUNT=0
CONTENT_UPDATE_COUNT=0
CONTENT_CHANGE_DETAILS=()

# --- Helper: Logging ---
log() {
    if [[ "$VERBOSE" == true ]]; then
        echo "[VERBOSE] $*" >&2
    fi
}
info() { echo "[INFO] $*"; }
warn() { echo "[WARN] $*" >&2; }
error() { echo "[ERROR] $*" >&2; }

# --- Helper: Build find exclude args ---
build_exclude_args() {
    local input="$1"
    local args=""
    if [[ -f "$input" ]]; then
        while IFS= read -r pattern; do
            [[ -z "$pattern" || "$pattern" =~ ^# ]] && continue
            args+=" -not -path '$pattern' "
        done < "$input"
    else
        # Portable: only the built-in EXCLUDE_PATHS array is supported as a name
        if [[ "$input" == "EXCLUDE_PATHS" ]]; then
            local pattern
            for pattern in "${EXCLUDE_PATHS[@]}"; do
                [[ -z "$pattern" || "$pattern" =~ ^# ]] && continue
                args+=" -not -path '$pattern' "
            done
        else
            return 1
        fi
    fi
    echo "$args"
}


# --- Helper: Should this path be skipped? ---
should_skip_path() {
    local path="$1"
    local base
    base=$(basename "$path")

    # Always protect the tool and restore script by basename
    case "$base" in
        file_manager_cli.sh|setup_test_env.sh|.DS_Store) return 0 ;;
    esac

    # Match against EXCLUDE_PATHS glob patterns (best-effort)
    local pattern
    for pattern in "${EXCLUDE_PATHS[@]}"; do
        # shellcheck disable=SC2254
        case "$path" in
            $pattern) return 0 ;;
        esac
    done
    return 1
}

# --- Core Function: Safe Move (Respects Dry-Run) ---
safe_move() {
    local src="$1"
    local dest="$2"
    local kind="${3:-item}"

    if [[ "$src" == "$dest" ]]; then return 0; fi
    if [[ -e "$dest" ]]; then
        warn "SKIP (exists): '$dest'"; return 1
    fi
    if [[ "$DRY_RUN" == true ]]; then
        echo "[DRY-RUN] Would rename $kind: '$src' -> '$dest'"
        if [[ "$kind" == "dir" ]]; then ((RENAME_DIR_COUNT++)); else ((RENAME_FILE_COUNT++)); fi
    else
        log "Renaming $kind: '$src' -> '$dest'"
        if mv -- "$src" "$dest"; then
            info "Renamed $kind: '$src' -> '$dest'"
            if [[ "$kind" == "dir" ]]; then ((RENAME_DIR_COUNT++)); else ((RENAME_FILE_COUNT++)); fi
        else
            warn "Failed to rename: '$src'"
            return 1
        fi
    fi
}

# --- Core Function: Rename Directories ---
rename_directories() {
    info "=== Renaming Directories ==="
    info "Rules: lowercase; '.', '-', spaces → '_'"
    local tmp
    tmp=$(mktemp)
    find . -depth -type d -print > "$tmp"
    while IFS= read -r dir; do
        [[ -z "$dir" ]] && continue
        local dirname_only=$(basename "$dir")
        local parent_path=$(dirname "$dir")
        [[ "$dirname_only" == "." ]] && continue
        if should_skip_path "$dir"; then
            log "Skip (excluded): $dir"
            continue
        fi

        local newname
        newname=$(printf "%s" "$dirname_only" | tr "[:upper:]" "[:lower:]")
        newname="${newname//./_}"
        newname="${newname//-/_}"
        newname="${newname// /_}"

        safe_move "$dir" "$parent_path/$newname" "dir"
    done < "$tmp"
    rm -f "$tmp"
}

# --- Core Function: Rename Files ---
rename_files() {
    info "=== Renaming Files ==="
    info "Rules: lowercase; '-', '_', spaces → '.'"
    local tmp
    tmp=$(mktemp)
    find . -type f -print > "$tmp"
    while IFS= read -r file; do
        [[ -z "$file" ]] && continue
        if should_skip_path "$file"; then
            log "Skip (excluded): $file"
            continue
        fi
        local filename_only=$(basename "$file")
        local parent_path=$(dirname "$file")

        local newname
        newname=$(printf "%s" "$filename_only" | tr "[:upper:]" "[:lower:]")
        newname="${newname//-/.}"
        newname="${newname//_/.}"
        newname="${newname// /.}"

        safe_move "$file" "$parent_path/$newname" "file"
    done < "$tmp"
    rm -f "$tmp"
}

# --- Helper: Compute the new name a file/dir would receive under the rules ---
compute_new_name() {
    local name="$1"
    local kind="$2"   # "file" or "dir"
    local new
    new=$(printf "%s" "$name" | tr "[:upper:]" "[:lower:]")
    if [[ "$kind" == "dir" ]]; then
        new="${new//./_}"
        new="${new//-/_}"
        new="${new// /_}"
    else
        new="${new//-/.}"
        new="${new//_/.}"
        new="${new// /.}"
    fi
    echo "$new"
}

# --- Helper: split basename into stem + extension (last suffix) ---
split_stem_ext() {
    local base="$1"
    if [[ "$base" == *.* && "$base" != .* ]]; then
        _STEM="${base%.*}"
        _EXT=".${base##*.}"
    else
        _STEM="$base"
        _EXT=""
    fi
}

# --- Helper: simple Title_Case for underscore/hyphen/space/dot stems ---
# helper_utils → Helper_Utils ; main.entry → Main.Entry
title_case_stem() {
    local s="$1"
    local out="" part first rest
    # normalize separators to _ for splitting, remember nothing — emit with _
    local norm="$s"
    norm="${norm//-/_}"
    norm="${norm// /_}"
    norm="${norm//./_}"
    local IFS='_'
    # shellcheck disable=SC2086
    set -- $norm
    for part in "$@"; do
        [[ -z "$part" ]] && continue
        first=$(printf "%s" "${part:0:1}" | tr "[:lower:]" "[:upper:]")
        rest=$(printf "%s" "${part:1}" | tr "[:upper:]" "[:lower:]")
        if [[ -n "$out" ]]; then
            out="${out}_${first}${rest}"
        else
            out="${first}${rest}"
        fi
    done
    printf "%s" "$out"
}

# --- Helper: add old|new to map file if old != new and old not already present ---
map_add() {
    local mapfile="$1" old="$2" new="$3"
    [[ -z "$old" || -z "$new" || "$old" == "$new" ]] && return 0
    if ! grep -qF -- "${old}|" "$mapfile" 2>/dev/null; then
        echo "${old}|${new}" >> "$mapfile"
    fi
}

# --- Helper: generate filename variants that should map to $target ---
# Includes original $source (if given), separator and case variants.
emit_variants_to_map() {
    local mapfile="$1"
    local source="$2"   # may be empty
    local target="$3"

    local candidates=()
    [[ -n "$source" ]] && candidates+=("$source")
    candidates+=("$target")

    local c stem ext low up title
    local sep_forms=()

    for c in "${candidates[@]}"; do
        split_stem_ext "$c"
        stem="$_STEM"
        ext="$_EXT"

        sep_forms=(
            "${stem}${ext}"
            "${stem//./_}${ext}"
            "${stem//./-}${ext}"
            "${stem//./ }${ext}"
            "${stem//_/.}${ext}"
            "${stem//_/-}${ext}"
            "${stem//_/ }${ext}"
            "${stem//-/.}${ext}"
            "${stem//-/_}${ext}"
            "${stem//-/ }${ext}"
            "${stem// /.}${ext}"
            "${stem// /_}${ext}"
            "${stem// /-}${ext}"
        )

        local f
        for f in "${sep_forms[@]}"; do
            [[ -z "$f" ]] && continue
            map_add "$mapfile" "$f" "$target"

            low=$(printf "%s" "$f" | tr "[:upper:]" "[:lower:]")
            up=$(printf "%s" "$f" | tr "[:lower:]" "[:upper:]")
            map_add "$mapfile" "$low" "$target"
            map_add "$mapfile" "$up" "$target"

            # Title_Case on stem (Helper_Utils.php style)
            split_stem_ext "$f"
            title="$(title_case_stem "$_STEM")${_EXT}"
            map_add "$mapfile" "$title" "$target"
            # also title with hyphen / dot separators commonly seen
            title="${title//_/-}"
            map_add "$mapfile" "$title" "$target"
            title="$(title_case_stem "$_STEM")"
            title="${title//_/.}${_EXT}"
            map_add "$mapfile" "$title" "$target"
        done
    done
}

# --- Build content rename map from current tree (call before or after renames) ---
# Writes old|new lines to $1 (mapfile path).
build_content_rename_map() {
    local mapfile="$1"
    : > "$mapfile"

    local listfile f current target
    listfile=$(mktemp)
    find . -type f -print > "$listfile"

    while IFS= read -r f; do
        [[ -z "$f" ]] && continue
        if should_skip_path "$f"; then
            log "Skip content map (excluded): $f"
            continue
        fi
        current=$(basename "$f")
        target=$(compute_new_name "$current" "file")
        # Always register variants → target (even if already renamed,
        # so leftover old refs in content are still found)
        emit_variants_to_map "$mapfile" "$current" "$target"
    done < "$listfile"
    rm -f "$listfile"

    # Drop identity mappings; keep longest keys first for apply order
    if [[ -s "$mapfile" ]]; then
        local sorted
        sorted=$(mktemp)
        awk -F'|' '$1 != $2 { print length($1), $0 }' "$mapfile" \
            | sort -nr | cut -d' ' -f2- | awk -F'|' '!seen[$1]++' > "$sorted"
        mv "$sorted" "$mapfile"
    fi
}

# --- Apply one old→new inside a temp file copy if context matches ---
# Sets globals: _APPLY_CHANGED (true/false)
apply_content_replacement() {
    local file="$1" ext="$2" old="$3" new="$4" tmp="$5"
    _APPLY_CHANGED=false

    grep -qF -- "$old" "$tmp" 2>/dev/null || return 0

    local pattern_matched=false
    local old_re
    old_re=$(printf "%s" "$old" | sed 's/[.[\*^$()+?{|]/g')

    case "$ext" in
        php)
            if grep -qE "(include|require)(_once)?[[:space:]]*(\\()?[[:space:]]*[\"'][^\"']*${old_re}[^\"']*[\"']" "$tmp" 2>/dev/null \
               || grep -qE "__DIR__[[:space:]]*\\.[[:space:]]*[\"'][^\"']*${old_re}[^\"']*[\"']" "$tmp" 2>/dev/null \
               || grep -qE "(src|href|action)=[\"'][^\"']*${old_re}[^\"']*[\"']" "$tmp" 2>/dev/null; then
                pattern_matched=true
            fi
            ;;
        html|htm)
            if grep -qE "(src|href|data-src|action)=[\"'][^\"']*${old_re}[^\"']*[\"']" "$tmp" 2>/dev/null; then
                pattern_matched=true
            fi
            ;;
        js)
            if grep -qE "(import|require)[[:space:]]*(\\()?[[:space:]]*[\"'][^\"']*${old_re}[^\"']*[\"']" "$tmp" 2>/dev/null \
               || grep -qE "from[[:space:]]+[\"'][^\"']*${old_re}[^\"']*[\"']" "$tmp" 2>/dev/null; then
                pattern_matched=true
            fi
            ;;
        css)
            if grep -qE "@import[[:space:]]+[\"'][^\"']*${old_re}[^\"']*[\"']" "$tmp" 2>/dev/null \
               || grep -qE "url\\([[:space:]]*[\"']?[^\"')]*${old_re}[^\"')]*[\"']?[[:space:]]*\\)" "$tmp" 2>/dev/null; then
                pattern_matched=true
            fi
            ;;
        sh|bash)
            if grep -qE "(^|[[:space:]])(\\.|source)[[:space:]]+[\"']?[^\"'[:space:]]*${old_re}[^\"'[:space:]]*[\"']?" "$tmp" 2>/dev/null \
               || grep -qE "\\./${old_re}" "$tmp" 2>/dev/null; then
                pattern_matched=true
            fi
            ;;
        *)
            if grep -qE "[\"'=/][^\"'[:space:]]*${old_re}[^\"'[:space:]]*[\"']?" "$tmp" 2>/dev/null; then
                pattern_matched=true
            fi
            ;;
    esac

    [[ "$pattern_matched" == true ]] || return 0

    log "In '$file' ($ext): context match for '$old' → '$new'"
    if [[ "$DRY_RUN" == true ]]; then
        echo "[DRY-RUN] Would update content in: '$file'"
        echo "          '$old'  →  '$new'"
        CONTENT_CHANGE_DETAILS+=("$file : '$old' → '$new'")
        _APPLY_CHANGED=true
        return 0
    fi

    local escaped_old newtmp
    escaped_old=$(printf "%s" "$old" | sed -e 's/\./\\./g' -e 's/\[/\\[/g' -e 's/\]/\\]/g' -e 's/\*/\\*/g' -e 's/\^/\\^/g' -e 's/\$/\\$/g' -e 's/(/\\(/g' -e 's/)/\\)/g' -e 's/+/\\+/g' -e 's/?/\\?/g' -e 's/{/\\{/g' -e 's/|/\\|/g')
    newtmp=$(mktemp)
    if sed "s|${escaped_old}|${new}|g" "$tmp" > "$newtmp" 2>/dev/null; then
        mv "$newtmp" "$tmp"
        CONTENT_CHANGE_DETAILS+=("$file : '$old' → '$new'")
        _APPLY_CHANGED=true
    else
        rm -f "$newtmp"
        warn "sed failed for '$old' in '$file'"
    fi
}

# --- Core Function: Update Content References ---
# ONLY rewrites strings that appear in known filename-reference contexts
# for the given file type. Ordinary variables / text are never touched.
#
# Patterns by file type:
#   .php  → include/require (+ optional __DIR__ concatenations) + HTML tags
#   .html → <script src>, <link href>, <img src> (and similar)
#   .js   → import / require
#   .css  → @import and url()
#   .sh   → source / . / ./file
#
update_references() {
    info "=== Updating File Content References ==="
    info "Only context-aware filename references are changed (by file type)."

    local mapfile listfile
    mapfile=$(mktemp)
    listfile=$(mktemp)
    trap 'rm -f "$mapfile" "$listfile"' RETURN

    build_content_rename_map "$mapfile"

    if [[ ! -s "$mapfile" ]]; then
        info "No filename renames to propagate into content."
        return
    fi

    log "Filename map contains $(wc -l < "$mapfile") entries"
    if [[ "$VERBOSE" == true ]]; then
        echo "[VERBOSE] Map (old → new):" >&2
        cat "$mapfile" >&2
    fi

    find . -type f -print > "$listfile"

    local file ext file_changed updated_this_file tmp old new
    while IFS= read -r file; do
        [[ -z "$file" ]] && continue
        if should_skip_path "$file"; then
            continue
        fi

        ext="${file##*.}"
        ext=$(printf "%s" "$ext" | tr "[:upper:]" "[:lower:]")

        case "$ext" in
            php|html|htm|js|css|sh|bash) ;;
            *)
                case "$file" in
                    *.md|*.txt|*.json|*.yml|*.yaml|*.xml) ;;
                    *) continue ;;
                esac
                ;;
        esac

        file_changed=false
        updated_this_file=0
        tmp=$(mktemp)
        cp "$file" "$tmp"

        while IFS='|' read -r old new; do
            [[ -z "$old" || -z "$new" || "$old" == "$new" ]] && continue
            apply_content_replacement "$file" "$ext" "$old" "$new" "$tmp"
            if [[ "$_APPLY_CHANGED" == true ]]; then
                file_changed=true
                ((updated_this_file++))
            fi
        done < "$mapfile"

        if [[ "$file_changed" == true ]]; then
            if [[ "$DRY_RUN" == false ]]; then
                mv "$tmp" "$file"
                ((CONTENT_UPDATE_COUNT++))
                info "Updated content: $file ($updated_this_file replacement(s))"
            else
                ((CONTENT_UPDATE_COUNT++))
                rm -f "$tmp"
            fi
        else
            rm -f "$tmp"
        fi
    done < "$listfile"

    info "Content scan complete."
}

# --- Summary Report ---
print_summary() {
    echo ""
    echo "=========================================="
    echo " SUMMARY REPORT"
    echo "=========================================="
    echo "Mode          : $([ "$DRY_RUN" == true ] && echo "DRY-RUN (no changes written)" || echo "LIVE")"
    echo "Directories   : $RENAME_DIR_COUNT renamed"
    echo "Files         : $RENAME_FILE_COUNT renamed"
    echo "Content files : $CONTENT_UPDATE_COUNT updated"
    if [[ ${#CONTENT_CHANGE_DETAILS[@]} -gt 0 ]]; then
        echo ""
        echo "Content changes detail:"
        for detail in "${CONTENT_CHANGE_DETAILS[@]}"; do
            echo "  • $detail"
        done
    else
        echo ""
        echo "Content changes detail: (none)"
    fi
    echo "=========================================="
}

# --- Check / Preview: force dry-run of selected (or all) actions and report ---
run_check() {
    info "=== CHECK / PREVIEW MODE (forced dry-run) ==="
    local saved_dry="$DRY_RUN"
    DRY_RUN=true
    RENAME_DIR_COUNT=0
    RENAME_FILE_COUNT=0
    CONTENT_UPDATE_COUNT=0
    CONTENT_CHANGE_DETAILS=()

    # If no specific actions selected, check everything
    if [[ "$DO_DIRS" == false && "$DO_FILES" == false && "$DO_CONTENT" == false && "$DO_ALL" == false ]]; then
        rename_directories
        rename_files
        update_references
    else
        [[ "$DO_ALL" == true || "$DO_DIRS" == true ]] && rename_directories
        [[ "$DO_ALL" == true || "$DO_FILES" == true ]] && rename_files
        [[ "$DO_ALL" == true || "$DO_CONTENT" == true ]] && update_references
    fi

    print_summary
    DRY_RUN="$saved_dry"

    if [[ $RENAME_DIR_COUNT -eq 0 && $RENAME_FILE_COUNT -eq 0 && $CONTENT_UPDATE_COUNT -eq 0 ]]; then
        info "RESULT: No changes needed. Everything already matches the rules."
    else
        info "RESULT: Changes are pending (see summary above). Re-run without check to apply."
    fi
}

# --- Core Function: Find Modified Items ---
find_modified_items() {
    local days="${1:-7}"
    local include_pattern="${2:-*}"
    local exclude_list="${3:-EXCLUDE_PATHS}"
    local exclude_args
    exclude_args=$(build_exclude_args "$exclude_list")

    info "=== Finding items modified in last $days days ==="
    if [[ "$DRY_RUN" == true ]]; then
        echo "[DRY-RUN] Would execute: find . -mtime -$days -name '$include_pattern' $exclude_args -print"
    else
        # shellcheck disable=SC2086
        eval "find . -mtime -$days -name '$include_pattern' $exclude_args -print"
    fi
}

# --- Interactive Menu ---
show_menu() {
    clear
    echo "=========================================="
    echo " FILE RENAMING & MANAGEMENT TOOL"
    echo "=========================================="
    echo "Current Mode: $([ "$DRY_RUN" == true ] && echo "TEST/DRY-RUN" || echo "LIVE")"
    echo "Verbose: $([ "$VERBOSE" == true ] && echo "ON" || echo "OFF")"
    echo "------------------------------------------"
    echo "FILESYSTEM RULES:"
    echo "  • All names → lowercase"
    echo "  • Dirs:  '.', '-', spaces → '_'  (_ allowed)"
    echo "  • Files: '-', '_', spaces → '.'"
    echo "CONTENT RULES (context-aware):"
    echo "  • .php/.html/.js/.css/.sh – only known reference patterns"
    echo "  • Variables / ordinary text are never touched"
    echo "------------------------------------------"
    echo "1. Rename Directories"
    echo "2. Rename Files (names)"
    echo "3. Update Content References"
    echo "4. Run Full Workflow (Dirs → Files → Content)"
    echo "5. Check / Preview (dry-run of needed changes)"
    echo "6. View Last Summary"
    echo "7. Find Modified Items (Last X Days)"
    echo "8. Toggle Verbose Mode (Current: $VERBOSE)"
    echo "9. Toggle Test/Dry-Run Mode (Current: $DRY_RUN)"
    echo "10. Show Exclude Patterns"
    echo "11. Exit"
    echo "=========================================="
}

main_menu() {
    local days_input
    PS3="Select an option: "
    local options=(
        "Rename Directories"
        "Rename Files (names)"
        "Update Content References"
        "Run Full Workflow"
        "Check / Preview (needed changes)"
        "View Last Summary"
        "Find Modified Items"
        "Toggle Verbose"
        "Toggle Test/Dry-Run"
        "Show Exclude Patterns"
        "Exit"
    )
    while true; do
        show_menu
        select opt in "${options[@]}"; do
            case $opt in
                "Rename Directories")
                    RENAME_DIR_COUNT=0
                    rename_directories
                    print_summary
                    read -p "Press Enter to continue..."
                    ;;
                "Rename Files (names)")
                    RENAME_FILE_COUNT=0
                    rename_files
                    print_summary
                    read -p "Press Enter to continue..."
                    ;;
                "Update Content References")
                    CONTENT_UPDATE_COUNT=0
                    CONTENT_CHANGE_DETAILS=()
                    update_references
                    print_summary
                    read -p "Press Enter to continue..."
                    ;;
                "Run Full Workflow")
                    if [[ "$DRY_RUN" == false ]]; then
                        read -p "WARNING: Live Mode! This will change files. Continue? (y/n): " confirm
                        [[ "$confirm" != "y" ]] && break
                    fi
                    RENAME_DIR_COUNT=0
                    RENAME_FILE_COUNT=0
                    CONTENT_UPDATE_COUNT=0
                    CONTENT_CHANGE_DETAILS=()
                    rename_directories
                    rename_files
                    update_references
                    info "Workflow Complete."
                    print_summary
                    read -p "Press Enter to continue..."
                    ;;
                "Check / Preview (needed changes)")
                    run_check
                    read -p "Press Enter to continue..."
                    ;;
                "View Last Summary")
                    print_summary
                    read -p "Press Enter to continue..."
                    ;;
                "Find Modified Items")
                    read -p "Enter number of days (default 7): " days_input
                    days_input=${days_input:-7}
                    find_modified_items "$days_input" "*" EXCLUDE_PATHS
                    read -p "Press Enter to continue..."
                    ;;
                "Toggle Verbose")
                    VERBOSE=$([ "$VERBOSE" == true ] && echo false || echo true)
                    info "Verbose mode set to: $VERBOSE"
                    break
                    ;;
                "Toggle Test/Dry-Run")
                    DRY_RUN=$([ "$DRY_RUN" == true ] && echo false || echo true)
                    info "Test/Dry-Run mode set to: $DRY_RUN"
                    break
                    ;;
                "Show Exclude Patterns")
                    info "Excluded paths:"
                    printf ' - %s\n' "${EXCLUDE_PATHS[@]}"
                    read -p "Press Enter to continue..."
                    break
                    ;;
                "Exit")
                    info "Exiting."
                    exit 0
                    ;;
                *)
                    warn "Invalid option. Try again."
                    break
                    ;;
            esac
            break
        done
    done
}

# --- CLI Argument Parsing ---
parse_args() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            -v|--verbose) VERBOSE=true; shift ;;
            -t|--test|--dry-run) DRY_RUN=true; shift ;;
            -a|--all) DO_ALL=true; shift ;;
            -d|--dirs) DO_DIRS=true; shift ;;
            -n|--names|--files) DO_FILES=true; shift ;;
            -c|--content) DO_CONTENT=true; shift ;;
            -h|--help)
                echo "Usage: $0 [OPTIONS]"
                echo ""
                echo "Options:"
                echo "  -v, --verbose          Enable verbose output"
                echo "  -t, --test, --dry-run  Show changes without applying them"
                echo "  -a, --all              Run full workflow (dirs + files + content)"
                echo "  -d, --dirs             Rename directories only"
                echo "  -n, --names, --files   Rename files (names) only"
                echo "  -c, --content          Update content references only"
                echo "  -h, --help             Show this help"
                echo "  (No args)              Launch interactive menu"
                echo ""
                echo "FILESYSTEM NAMING RULES:"
                echo "  • Both files and directories MUST be lowercase"
                echo "  • Directories: '.', '-', spaces → '_'  (_ allowed)"
                echo "  • Files:       '-', '_', spaces → '.'"
                echo ""
                echo "CONTENT UPDATE RULES (context-aware by file type):"
                echo "  • .php  → include/require + __DIR__ concatenations + HTML attrs"
                echo "  • .html → <script src>, <link href>, <img src>, ..."
                echo "  • .js   → import / require / from"
                echo "  • .css  → @import and url()"
                echo "  • .sh   → source / . / ./file"
                echo "  • Ordinary variables or plain text are never touched."
                echo "  • Example changed:  include \"rick_seg1_seg.php\""
                echo "                   →  include \"rick.seg1.seg.php\""
                echo "  • Example NOT changed:  \$my_var_name  or  some_text_with_underscores"
                echo ""
                echo "Examples:"
                echo "  $0 -a -t          # dry-run full workflow"
                echo "  $0 -d -n          # rename dirs + files (live)"
                echo "  $0 -c -v          # update content only, verbose"
                echo "  $0 -a             # live full workflow"
                exit 0
                ;;
            *) error "Unknown option: $1"; exit 1 ;;
        esac
    done
}

# --- Entry Point ---
parse_args "$@"

RENAME_DIR_COUNT=0
RENAME_FILE_COUNT=0
CONTENT_UPDATE_COUNT=0
CONTENT_CHANGE_DETAILS=()

# Decide mode
if [[ "$DO_ALL" == true || "$DO_DIRS" == true || "$DO_FILES" == true || "$DO_CONTENT" == true ]]; then
    # CLI selective / full mode
    info "Running in CLI Mode (Verbose: $VERBOSE, Dry-Run: $DRY_RUN)"
    if [[ "$DO_ALL" == true ]]; then
        rename_directories
        rename_files
        update_references
    else
        [[ "$DO_DIRS" == true ]] && rename_directories
        [[ "$DO_FILES" == true ]] && rename_files
        [[ "$DO_CONTENT" == true ]] && update_references
    fi
    print_summary
elif [[ "$VERBOSE" == true || "$DRY_RUN" == true ]]; then
    # Legacy: flags without action → treat as full workflow (compat)
    info "Running in CLI Mode (Verbose: $VERBOSE, Dry-Run: $DRY_RUN) – full workflow"
    rename_directories
    rename_files
    update_references
    print_summary
else
    # No flags → interactive menu
    main_menu
fi

