#!/bin/bash

# filem - Unified save tool for AGENTS.md, plugins, skills, and subagents
# Usage: filem
# Interactive 4-column selection mode for saving files

set -e

STORAGE_DIR="$HOME/00_central/volatile"
TYPE_DESC_FILE="$STORAGE_DIR/.type_descriptions"
PLUGINS_DIR=".opencode/plugins"
SKILLS_DIR=".opencode/skills"
AGENTS_DIR=".opencode/agents"
ASKILLS_DIR=".agents/skills"
CURRENT_DIR="$(pwd)"

# Check dependencies
compare_files() {
    local f1="$1"
    local f2="$2"
    if command -v icdiff >/dev/null 2>&1; then
        icdiff "$f1" "$f2" -t --show-no-spaces --no-bold | grep -ve "^\s*$" || true
    else
        diff -u "$f1" "$f2" || true
    fi
}

load_type_descriptions() {
    TYPE_DESCRIPTIONS=()
    if [[ -f "$TYPE_DESC_FILE" ]]; then
        while IFS='|' read -r cat type_name desc; do
            TYPE_DESCRIPTIONS["${cat}:${type_name}"]="$desc"
        done < "$TYPE_DESC_FILE"
    fi
}

save_type_description() {
    local category="$1"
    local type_name="$2"
    local description="$3"
    local tmp_file
    tmp_file=$(mktemp)
    if [[ -f "$TYPE_DESC_FILE" ]]; then
        grep -v "^${category}|${type_name}|" "$TYPE_DESC_FILE" > "$tmp_file" 2>/dev/null || true
    else
        : > "$tmp_file"
    fi
    echo "${category}|${type_name}|${description}" >> "$tmp_file"
    mv "$tmp_file" "$TYPE_DESC_FILE"
}

# Ensure storage exists
mkdir -p "$STORAGE_DIR"

# --- Data Gathering ---

# Column 1: Trackable .md files (AGENTS.md, CLAUDE.md, etc.)
get_trackable_md_files() {
    local tracked_files=$(ls "$STORAGE_DIR" 2>/dev/null | grep -vE "_PLUGIN|_SKILL|_AGENT$" | sed -E 's/.*_(.*)/\1/' | sort -u)
    local result=()
    for file in $tracked_files; do
        if [[ -f "$CURRENT_DIR/$file" ]]; then
            result+=("$file")
        fi
    done
    # Also check for AGENTS.md and CLAUDE.md in current dir if not tracked yet
    for md_file in AGENTS.md CLAUDE.md; do
        if [[ -f "$CURRENT_DIR/$md_file" ]]; then
            local found=0
            for tracked in "${result[@]}"; do
                if [[ "$tracked" == "$md_file" ]]; then
                    found=1
                    break
                fi
            done
            if [[ $found -eq 0 ]]; then
                result+=("$md_file")
            fi
        fi
    done
    printf '%s\n' "${result[@]}"
}

# Column 2: Available plugins
get_available_plugins() {
    local result=()
    if [[ -d "$PLUGINS_DIR" ]]; then
        while IFS= read -r -d '' file; do
            result+=("$(basename "$file")")
        done < <(find "$PLUGINS_DIR" -maxdepth 1 -type f \
            ! -name "*~" \
            ! -name "#*#" \
            ! -name ".#*" \
            -print0 | sort -z)
    fi
    printf '%s\n' "${result[@]}"
}

# Column 3: Available skills (from both .opencode/skills and .agents/skills)
# SKILL_SOURCES maps skill_name -> "opencode"|"agents"|"both"
get_available_skills() {
    local result=()
    local -A seen_skills

    if [[ -d "$SKILLS_DIR" ]]; then
        for dir in "$SKILLS_DIR"/*; do
            if [[ -d "$dir" && -f "$dir/SKILL.md" ]]; then
                local name="$(basename "$dir")"
                if [[ -z "${seen_skills[$name]}" ]]; then
                    seen_skills["$name"]=1
                    result+=("$name")
                fi
                SKILL_SOURCES["$name"]="opencode"
            fi
        done
    fi

    if [[ -d "$ASKILLS_DIR" ]]; then
        for dir in "$ASKILLS_DIR"/*; do
            if [[ -d "$dir" && -f "$dir/SKILL.md" ]]; then
                local name="$(basename "$dir")"
                if [[ -z "${seen_skills[$name]}" ]]; then
                    seen_skills["$name"]=1
                    result+=("$name")
                    SKILL_SOURCES["$name"]="agents"
                else
                    SKILL_SOURCES["$name"]="both"
                fi
            fi
        done
    fi

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

# Column 4: Available subagents
get_available_subagents() {
    local result=()
    if [[ -d "$AGENTS_DIR" ]]; then
        while IFS= read -r -d '' file; do
            local basename=$(basename "$file")
            # Remove .md extension for display
            local name="${basename%.md}"
            result+=("$name")
        done < <(find "$AGENTS_DIR" -maxdepth 1 -type f -name "*.md" \
            ! -name "*~" \
            ! -name "#*#" \
            ! -name ".#*" \
            -print0 | sort -z)
    fi
    printf '%s\n' "${result[@]}"
}

# Get existing types for a given MD file
get_types_for_md_file() {
    local md_file="$1"
    ls "$STORAGE_DIR" 2>/dev/null | grep "_${md_file}$" | sed -E 's/.*_([^_]+)_.*/\1/' | sort -u
}

# Selection states
SELECTED_MD_FILE=""
declare -A SELECTED_PLUGINS
declare -A SELECTED_SKILLS
declare -A SELECTED_SUBAGENTS
declare -A SKILL_SOURCES
declare -A TYPE_DESCRIPTIONS

MD_FILES=($(get_trackable_md_files))
AVAILABLE_PLUGINS=($(get_available_plugins))
AVAILABLE_SKILLS=($(get_available_skills))
AVAILABLE_SUBAGENTS=($(get_available_subagents))

# Index-to-display: 1..9, 11..N (skip 10)
_idx2disp() { local i=$1; if [[ $i -lt 9 ]]; then echo $((i+1)); else echo $((i+2)); fi; }
# Display-to-index: inverse
_disp2idx() { local n=$1; if [[ $n -le 9 ]]; then echo $((n-1)); else echo $((n-2)); fi; }

# --- UI Functions ---

draw_menu() {
    clear
    echo -e "\033[33m=== filem - Unified Save Tool ===\033[0m"
    echo ""
    printf "%-25s %-25s %-25s %-25s\n" "COL 1: MD FILES" "COL 2: PLUGINS" "COL 3: SKILLS(@*ag)" "COL 4: SUBAGENTS"
    printf "%-25s %-25s %-25s %-25s\n" "---------------" "--------------" "-------------" "----------------"

    local max_rows=${#MD_FILES[@]}
    [[ ${#AVAILABLE_PLUGINS[@]} -gt $max_rows ]] && max_rows=${#AVAILABLE_PLUGINS[@]}
    [[ ${#AVAILABLE_SKILLS[@]} -gt $max_rows ]] && max_rows=${#AVAILABLE_SKILLS[@]}
    [[ ${#AVAILABLE_SUBAGENTS[@]} -gt $max_rows ]] && max_rows=${#AVAILABLE_SUBAGENTS[@]}

    for ((i=0; i<max_rows; i++)); do
        # Column 1: MD Files (numbered keys, skip 10)
        local col1_text=""
        if [[ $i -lt ${#MD_FILES[@]} ]]; then
            local file="${MD_FILES[$i]}"
            local key=$(_idx2disp $i)
            local mark="[ ]"
            [[ "$SELECTED_MD_FILE" == "$file" ]] && mark="[x]"
            col1_text="${key}) $mark $file"
        fi

        # Column 2: Plugins (keys a-i)
        local col2_text=""
        if [[ $i -lt ${#AVAILABLE_PLUGINS[@]} ]]; then
            local plugin="${AVAILABLE_PLUGINS[$i]}"
            local key_code=$((97 + i)) # 'a' is 97
            local key=$(printf "\\$(printf '%03o' $key_code)")
            local mark="[ ]"
            [[ "${SELECTED_PLUGINS[$plugin]}" == "1" ]] && mark="[x]"
            # Truncate long plugin names
            local display_name="$plugin"
            if [[ ${#display_name} -gt 18 ]]; then
                display_name="${display_name:0:15}..."
            fi
            col2_text="${key}) $mark $display_name"
        fi

        # Column 3: Skills (keys j-r)
        local col3_text=""
        if [[ $i -lt ${#AVAILABLE_SKILLS[@]} ]]; then
            local skill="${AVAILABLE_SKILLS[$i]}"
            local key_code=$((106 + i)) # 'j' is 106
            local key=$(printf "\\$(printf '%03o' $key_code)")
            local mark="[ ]"
            [[ "${SELECTED_SKILLS[$skill]}" == "1" ]] && mark="[x]"
            local source_tag=""
            case "${SKILL_SOURCES[$skill]}" in
                "agents") source_tag="@" ;;
                "both") source_tag="*" ;;
            esac
            col3_text="${key}) $mark ${skill}${source_tag}"
        fi

        # Column 4: Subagents (keys s-z)
        local col4_text=""
        if [[ $i -lt ${#AVAILABLE_SUBAGENTS[@]} ]]; then
            local subagent="${AVAILABLE_SUBAGENTS[$i]}"
            local key_code=$((115 + i)) # 's' is 115
            local key=$(printf "\\$(printf '%03o' $key_code)")
            local mark="[ ]"
            [[ "${SELECTED_SUBAGENTS[$subagent]}" == "1" ]] && mark="[x]"
            col4_text="${key}) $mark $subagent"
        fi

        printf "%-25s %-25s %-25s %-25s\n" "$col1_text" "$col2_text" "$col3_text" "$col4_text"
    done

    echo ""
    echo -e "\033[33m[number]: MD file | [a-i]: Plugins | [j-r]: Skills | [s-z]: Subagents | [ENTER]: Save | [q]: Quit\033[0m"
    echo -e "\033[2mSkills: @=.agents only, *=.opencode+.agents\033[0m"
}

# Prompt for type selection when saving MD file
# Global variable to hold the selected type
SELECTED_MD_TYPE=""

prompt_for_md_type() {
    local md_file="$1"
    SELECTED_MD_TYPE=""
    
    local types=($(get_types_for_md_file "$md_file"))
    
    if [[ ${#types[@]} -eq 0 ]]; then
        # No existing types, ask for new one
        echo "" >&2
        echo -e "\033[7m\033[33m=== WAITING FOR INPUT ===\033[0m" >&2
        echo -e "\033[33mFile: $md_file\033[0m" >&2
        echo -en "\033[33mEnter type tag: \033[0m" >&2
        read TYPE
        if [[ -z "$TYPE" ]]; then
            echo -e "\033[31mInvalid type\033[0m" >&2
            return 1
        fi
        local NEW_DESC=""
        echo -en "\033[33mEnter description: \033[0m" >&2
        read NEW_DESC
        if [[ -z "$NEW_DESC" ]]; then
            echo -e "\033[31mDescription is required\033[0m" >&2
            return 1
        fi
        save_type_description "$md_file" "$TYPE" "$NEW_DESC"
        SELECTED_MD_TYPE="$TYPE"
        return 0
    fi
    
    echo "" >&2
    echo -e "\033[7m\033[33m=== WAITING FOR INPUT ===\033[0m" >&2
    echo -e "\033[33mFile: $md_file\033[0m" >&2
    echo "Select type:" >&2
    echo "---" >&2
    for i in "${!types[@]}"; do
        local type="${types[$i]}"
        local desc="${TYPE_DESCRIPTIONS["${md_file}:${type}"]}"
        local dnum=$(_idx2disp "$i")
        if [[ -n "$desc" ]]; then
            printf "%2s) \033[32m%-20s\033[0m  \033[2m%s\033[0m\n" "$dnum" "$type" "$desc" >&2
        else
            printf "%2s) \033[32m%s\033[0m\n" "$dnum" "$type" >&2
        fi
    done
    echo "---" >&2
    echo -e "n) \033[32mnew type\033[0m" >&2
    local maxdisp=$(_idx2disp $((${#types[@]}-1)))
    echo -en "\033[33mSelection (1-${maxdisp}, n for new type, q to quit): \033[0m" >&2
    # Clear any pending input first
    while IFS= read -r -t 0; do : ; done 2>/dev/null || true
    read -r REPLY
    
    if [[ "$REPLY" =~ ^[qQ]$ ]]; then
        return 1
    fi
    
    if [[ "$REPLY" =~ ^[nN]$ ]]; then
        echo -en "\033[33mEnter new type: \033[0m" >&2
        read TYPE
        if [[ -z "$TYPE" ]]; then
            echo -e "\033[31mInvalid type\033[0m" >&2
            return 1
        fi
        local NEW_DESC=""
        echo -en "\033[33mEnter description: \033[0m" >&2
        read NEW_DESC
        if [[ -z "$NEW_DESC" ]]; then
            echo -e "\033[31mDescription is required\033[0m" >&2
            return 1
        fi
        save_type_description "$md_file" "$TYPE" "$NEW_DESC"
        SELECTED_MD_TYPE="$TYPE"
        return 0
    elif [[ "$REPLY" =~ ^[0-9]+$ ]] && [[ "$REPLY" -ne 10 ]]; then
        local sel_idx=$(_disp2idx "$REPLY")
        if [[ $sel_idx -ge 0 ]] && [[ $sel_idx -lt ${#types[@]} ]]; then
            SELECTED_MD_TYPE="${types[$sel_idx]}"
            return 0
        fi
    else
        echo -e "\033[31mInvalid selection\033[0m" >&2
        return 1
    fi
}

# Prompt for plugin type tag (auto-uses default)
prompt_for_plugin_type() {
    local plugin_name="$1"
    local basename="${plugin_name%.*}"
    
    echo -e "\033[33mUsing default type tag: $basename\033[0m" >&2
    echo "$basename"
}

# Prompt for skill type tag (auto-uses default)
prompt_for_skill_type() {
    local skill_name="$1"
    
    echo -e "\033[33mUsing default type tag: $skill_name\033[0m" >&2
    echo "$skill_name"
}



# --- Save Logic ---

save_md_file() {
    local md_file="$1"
    
    if [[ ! -f "$md_file" ]]; then
        echo -e "\033[31mFile not found: $md_file\033[0m"
        return 1
    fi
    
    prompt_for_md_type "$md_file"
    if [[ $? -ne 0 ]]; then
        echo -e "\033[31mAborted saving $md_file\033[0m"
        return 1
    fi
    
    local type="$SELECTED_MD_TYPE"
    
    echo -e "\n\033[34m>>> Saving $md_file (type: $type)\033[0m"
    
    local latest_file=$(ls -t "$STORAGE_DIR"/*_"${type}_${md_file}" 2>/dev/null | head -1)
    
    if [[ -n "$latest_file" ]]; then
        echo "Comparing with latest version:"
        echo "---"
        
        if cmp -s "$latest_file" "$md_file"; then
            echo -e "\033[33mNo changes detected in $md_file\033[0m"
            echo -e "\033[32mSkipping save (file unchanged)\033[0m"
            return 0
        else
            compare_files "$latest_file" "$md_file"
            echo "---"
            echo -n -e "\033[33mSave new version? (y/N) \033[0m"
            read -n 1 -r
            echo
            if [[ ! "$REPLY" =~ ^[Yy]$ ]]; then
                echo -e "\033[31mSkipped saving $md_file\033[0m"
                return 0
            fi
        fi
    fi
    
    local timestamp=$(date +%Y%m%d_%H%M%S)
    local new_file="${STORAGE_DIR}/${timestamp}_${type}_${md_file}"
    cp "$md_file" "$new_file"
    echo -e "\033[32mSaved to: $new_file\033[0m"
}

save_plugin() {
    local plugin_name="$1"
    local plugin_path="$PLUGINS_DIR/$plugin_name"
    
    if [[ ! -f "$plugin_path" ]]; then
        echo -e "\033[31mPlugin not found: $plugin_path\033[0m"
        return 1
    fi
    
    # Get extension
    local ext="${plugin_name##*.}"
    if [[ "$ext" == "$plugin_name" ]]; then
        ext=""
    fi
    local basename="${plugin_name%.*}"
    
    echo ""
    local type_tag
    type_tag=$(prompt_for_plugin_type "$plugin_name")
    
    echo -e "\n\033[34m>>> Saving plugin $plugin_name (type: $type_tag)\033[0m"
    
    local latest_file
    if [[ -n "$ext" ]]; then
        latest_file=$(ls -t "$STORAGE_DIR"/*_"${type_tag}_PLUGIN.${ext}" 2>/dev/null | head -1)
    else
        latest_file=$(ls -t "$STORAGE_DIR"/*_"${type_tag}_PLUGIN" 2>/dev/null | head -1)
    fi
    
    if [[ -n "$latest_file" ]]; then
        if diff -q "$latest_file" "$plugin_path" > /dev/null; then
            echo -e "\033[33mNo changes. Skipping save.\033[0m"
            return 0
        else
            echo "---"
            echo -e "\033[33mPlugin differs from latest saved version.\033[0m"
            echo ""
            compare_files "$latest_file" "$plugin_path"
            echo ""
            echo -n -e "Press \033[33mEnter\033[0m to save, Ctrl+C to abort: "
            read -r
        fi
    fi
    
    local timestamp=$(date +%Y%m%d_%H%M%S)
    local new_file
    if [[ -n "$ext" ]]; then
        new_file="${STORAGE_DIR}/${timestamp}_${type_tag}_PLUGIN.${ext}"
    else
        new_file="${STORAGE_DIR}/${timestamp}_${type_tag}_PLUGIN"
    fi
    
    cp "$plugin_path" "$new_file"
    echo -e "\033[32mSaved plugin to: $new_file\033[0m"
}

save_skill() {
    local skill_name="$1"
    local skill_dir="$SKILLS_DIR/$skill_name"
    local askill_dir="$ASKILLS_DIR/$skill_name"
    local source="${SKILL_SOURCES[$skill_name]}"

    if [[ "$source" != "opencode" ]] && [[ "$source" != "agents" ]] && [[ "$source" != "both" ]]; then
        echo -e "\033[31mSkill directory not found: $skill_dir or $askill_dir\033[0m"
        return 1
    fi

    echo ""
    local type_tag
    type_tag=$(prompt_for_skill_type "$skill_name")

    local source_label="$source"
    [[ "$source" == "opencode" ]] && source_label=".opencode"
    [[ "$source" == "agents" ]] && source_label=".agents"
    [[ "$source" == "both" ]] && source_label=".opencode+.agents"
    echo -e "\n\033[34m>>> Saving skill $skill_name (type: $type_tag) [$source_label]\033[0m"

    local new_file="${STORAGE_DIR}/$(date +%Y%m%d_%H%M%S)_${type_tag}_SKILL.tar.gz"
    local latest_file=$(ls -t "$STORAGE_DIR"/*_"${type_tag}_SKILL.tar.gz" 2>/dev/null | head -1)

    local has_opencode=0
    local has_agents=0
    [[ -d "$skill_dir" ]] && has_opencode=1
    [[ -d "$askill_dir" ]] && has_agents=1

    if [[ -n "$latest_file" ]]; then
        local temp_dir=$(mktemp -d)
        tar -xzf "$latest_file" -C "$temp_dir"

        local need_save=0
        local diff_parts=""

        if [[ $has_opencode -eq 1 ]]; then
            local archive_oc="$temp_dir/$skill_name"
            if [[ -d "$archive_oc" ]]; then
                local d=$(diff -rq \
                    --exclude="*undo-tree~" \
                    --exclude="__pycache__" \
                    --exclude="*~" \
                    --exclude="*.pyc" \
                    --exclude="*.pyo" \
                    "$archive_oc" "$skill_dir" 2>&1 || true)
                if [[ -n "$d" ]]; then
                    diff_parts+="$d"
                    need_save=1
                fi
            else
                diff_parts+="[.opencode] New skill directory"$'\n'
                need_save=1
            fi
        fi

        if [[ $has_agents -eq 1 ]]; then
            local archive_ag="$temp_dir/.agents/skills/$skill_name"
            if [[ -d "$archive_ag" ]]; then
                local d=$(diff -rq \
                    --exclude="*undo-tree~" \
                    --exclude="__pycache__" \
                    --exclude="*~" \
                    --exclude="*.pyc" \
                    --exclude="*.pyo" \
                    "$archive_ag" "$askill_dir" 2>&1 || true)
                if [[ -n "$d" ]]; then
                    diff_parts+="$d"
                    need_save=1
                fi
            else
                diff_parts+="[.agents] New skill directory"$'\n'
                need_save=1
            fi
        fi

        rm -rf "$temp_dir"

        if [[ $need_save -eq 1 ]]; then
            echo "---"
            echo -e "\033[33mFiles that differ:\033[0m"
            echo "$diff_parts" | sed "s|$skill_dir/||g; s|$askill_dir/||g"
            echo ""
            echo -n -e "Press \033[33mEnter\033[0m to save, Ctrl+C to abort: "
            read -r
        else
            echo -e "\033[33mNo changes. Skipping save.\033[0m"
            return 0
        fi
    fi

    # Create staging directory for archive
    local stage_dir=$(mktemp -d)

    if [[ $has_opencode -eq 1 ]]; then
        cp -a "$skill_dir" "$stage_dir/$skill_name"
    fi

    if [[ $has_agents -eq 1 ]]; then
        mkdir -p "$stage_dir/.agents/skills"
        cp -a "$askill_dir" "$stage_dir/.agents/skills/$skill_name"
    fi

    local tar_items=()
    if [[ $has_opencode -eq 1 ]]; then
        tar_items+=("$skill_name")
    fi
    if [[ $has_agents -eq 1 ]]; then
        tar_items+=(".agents")
    fi

    tar -czf "$new_file" -C "$stage_dir" \
        --exclude="*undo-tree~" \
        --exclude="__pycache__" \
        --exclude="*~" \
        --exclude="*.pyc" \
        --exclude="*.pyo" \
        "${tar_items[@]}"

    rm -rf "$stage_dir"
    echo -e "\033[32mSaved skill archive to: $new_file\033[0m"
}

save_subagent() {
    local subagent_name="$1"
    local subagent_path="$AGENTS_DIR/${subagent_name}.md"
    local type_tag="$subagent_name"
    
    if [[ ! -f "$subagent_path" ]]; then
        echo -e "\033[31mSubagent not found: $subagent_path\033[0m"
        return 1
    fi
    
    echo -e "\n\033[34m>>> Saving subagent $subagent_name\033[0m"
    
    local latest_file=$(ls -t "$STORAGE_DIR"/*"_${type_tag}_SUBAGENT.md" 2>/dev/null | head -1)
    
    if [[ -n "$latest_file" ]]; then
        echo "Comparing with latest version:"
        echo "---"
        
        if cmp -s "$latest_file" "$subagent_path"; then
            echo -e "\033[33mNo changes detected in $subagent_name\033[0m"
            echo -e "\033[32mSkipping save (file unchanged)\033[0m"
            return 0
        else
            compare_files "$latest_file" "$subagent_path"
            echo "---"
            echo -n -e "\033[33mSave new version? (y/N) \033[0m"
            read -n 1 -r
            echo
            if [[ ! "$REPLY" =~ ^[Yy]$ ]]; then
                echo -e "\033[31mSkipped saving $subagent_name\033[0m"
                return 0
            fi
        fi
    fi
    
    local timestamp=$(date +%Y%m%d_%H%M%S)
    local new_file="${STORAGE_DIR}/${timestamp}_${type_tag}_SUBAGENT.md"
    cp "$subagent_path" "$new_file"
    echo -e "\033[32mSaved subagent to: $new_file\033[0m"
}

load_type_descriptions

# --- Main Loop ---

while true; do
    draw_menu
    read -r input
    
    case "$input" in
        q|Q)
            echo -e "\033[31mAborted.\033[0m"
            exit 0
            ;;
        "")
            break
            ;;
        [a-i])
            printf -v idx "%d" "'${input:0:1}"
            idx=$((idx - 97))
            if [[ $idx -lt ${#AVAILABLE_PLUGINS[@]} ]]; then
                plugin="${AVAILABLE_PLUGINS[$idx]}"
                if [[ "${SELECTED_PLUGINS[$plugin]}" == "1" ]]; then
                    unset SELECTED_PLUGINS["$plugin"]
                else
                    SELECTED_PLUGINS[$plugin]="1"
                fi
            fi
            ;;
        [j-r])
            printf -v idx "%d" "'${input:0:1}"
            idx=$((idx - 106))
            if [[ $idx -lt ${#AVAILABLE_SKILLS[@]} ]]; then
                skill="${AVAILABLE_SKILLS[$idx]}"
                if [[ "${SELECTED_SKILLS[$skill]}" == "1" ]]; then
                    unset SELECTED_SKILLS["$skill"]
                else
                    SELECTED_SKILLS[$skill]="1"
                fi
            fi
            ;;
        [s-z])
            printf -v idx "%d" "'${input:0:1}"
            idx=$((idx - 115))
            if [[ $idx -lt ${#AVAILABLE_SUBAGENTS[@]} ]]; then
                subagent="${AVAILABLE_SUBAGENTS[$idx]}"
                if [[ "${SELECTED_SUBAGENTS[$subagent]}" == "1" ]]; then
                    unset SELECTED_SUBAGENTS["$subagent"]
                else
                    SELECTED_SUBAGENTS[$subagent]="1"
                fi
            fi
            ;;
        *)
            if [[ "$input" =~ ^[0-9]+$ ]] && [[ "$input" -ne 10 ]] && [[ "$input" -ge 1 ]]; then
                idx=$(_disp2idx "$input")
                if [[ $idx -ge 0 ]] && [[ $idx -lt ${#MD_FILES[@]} ]]; then
                    file="${MD_FILES[$idx]}"
                    if [[ "$SELECTED_MD_FILE" == "$file" ]]; then
                        SELECTED_MD_FILE=""
                    else
                        SELECTED_MD_FILE="$file"
                    fi
                fi
            fi
            ;;
    esac
done

# --- Execute Saves ---

# Clear any leftover input before starting saves
while IFS= read -r -t 0.1; do : ; done 2>/dev/null || true

clear
echo -e "\033[33m=== Processing Saves ===\033[0m"
echo ""

if [[ -n "$SELECTED_MD_FILE" ]]; then
    save_md_file "$SELECTED_MD_FILE"
fi

for plugin in "${!SELECTED_PLUGINS[@]}"; do
    save_plugin "$plugin"
done

for skill in "${!SELECTED_SKILLS[@]}"; do
    save_skill "$skill"
done

for subagent in "${!SELECTED_SUBAGENTS[@]}"; do
    save_subagent "$subagent"
done

echo ""
echo -e "\033[32mAll tasks completed.\033[0m"
