#!/bin/bash

# filemd_restore - Consolidated restore tool for AGENTS.md, plugins, skills, and subagents
# Usage: filemd_restore
# Interactive 4-column selection mode

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"

# 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
}

# Ensure storage exists
mkdir -p "$STORAGE_DIR"

# --- Data Gathering ---

# Fixed timestamp length (YYYYMMDD_HHMMSS_)
TS_LEN=16

get_types() {
    local pattern="$1"
    local suffix="$2"
    ls "$STORAGE_DIR" 2>/dev/null | grep -E "$pattern" | while read -r file; do
        # Strip prefix and suffix
        local type_part="${file:$TS_LEN}"
        echo "${type_part%$suffix}"
    done | sort -u
}

# Column 1: AGENTS.md types
AGENT_TYPES=($(get_types "_AGENTS.md$" "_AGENTS.md"))
# Column 2: Plugin types
PLUGIN_TYPES=($(get_types "_PLUGIN" "_PLUGIN*"))
# Column 3: Skill types
SKILL_TYPES=($(get_types "_SKILL.tar.gz$" "_SKILL.tar.gz"))
# Column 4: Subagent types
SUBAGENT_TYPES=($(get_types "_SUBAGENT.md$" "_SUBAGENT.md"))

# 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; }
_disp2idx() { local n=$1; if [[ $n -le 9 ]]; then echo $((n-1)); else echo $((n-2)); fi; }

# Selection states
SELECTED_AGENT=""
declare -A SELECTED_PLUGINS
declare -A SELECTED_SKILLS
declare -A SELECTED_SUBAGENTS
declare -A TYPE_DESCRIPTIONS
LAST_DESC=""

# Key mappings
# 1-9 for Agents
# a-i for Plugins
# j-r for Skills
# s-z for Subagents

# --- UI Functions ---

draw_menu() {
    clear
    echo -e "\033[33m=== filemd_restore - Consolidated Selection ===\033[0m"
    echo ""
    printf "%-25s %-25s %-25s %-25s\n" "COL 1: AGENTS.md" "COL 2: PLUGINS" "COL 3: SKILLS" "COL 4: SUBAGENTS"
    printf "%-25s %-25s %-25s %-25s\n" "----------------" "--------------" "-------------" "----------------"

    local max_rows=${#AGENT_TYPES[@]}
    [[ ${#PLUGIN_TYPES[@]} -gt $max_rows ]] && max_rows=${#PLUGIN_TYPES[@]}
    [[ ${#SKILL_TYPES[@]} -gt $max_rows ]] && max_rows=${#SKILL_TYPES[@]}
    [[ ${#SUBAGENT_TYPES[@]} -gt $max_rows ]] && max_rows=${#SUBAGENT_TYPES[@]}

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

        # Column 2: Plugins (keys a-i)
        local col2_text=""
        if [[ $i -lt ${#PLUGIN_TYPES[@]} ]]; then
            local type="${PLUGIN_TYPES[$i]}"
            local key_code=$((97 + i)) # 'a' is 97
            local key=$(printf "\\$(printf '%03o' $key_code)")
            local mark="[ ]"
            [[ "${SELECTED_PLUGINS[$type]}" == "1" ]] && mark="[x]"
            # Truncate long plugin names
            local display_name="$type"
            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 ${#SKILL_TYPES[@]} ]]; then
            local type="${SKILL_TYPES[$i]}"
            local key_code=$((106 + i)) # 'j' is 106
            local key=$(printf "\\$(printf '%03o' $key_code)")
            local mark="[ ]"
            [[ "${SELECTED_SKILLS[$type]}" == "1" ]] && mark="[x]"
            col3_text="${key}) $mark $type"
        fi

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

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

    echo ""
    echo -e "\033[33m[number]: Agents | [a-i]: Plugins | [j-r]: Skills | [s-z]: Subagents | [ENTER]: Confirm | [q]: Quit\033[0m"
    if [[ -n "$LAST_DESC" ]]; then
        echo ""
        echo -e "\033[2m${LAST_DESC}\033[0m"
    fi
}

# --- Restoration Logic ---

restore_agent() {
    local type="$1"
    local md_file="AGENTS.md"
    echo -e "\n\033[34m>>> Processing AGENTS.md ($type)\033[0m"
    
    local latest=$(ls -t "$STORAGE_DIR"/*"${type}_${md_file}" 2>/dev/null | head -1)
    if [[ -z "$latest" ]]; then
        echo -e "\033[31mError: Stored file not found for type $type\033[0m"
        return
    fi

    if [[ -f "$md_file" ]]; then
        if ! diff -q "$md_file" "$latest" > /dev/null; then
            echo "Differences found in $md_file:"
            compare_files "$md_file" "$latest"
            echo -n -e "\033[33mOverwrite $md_file? (y/N) \033[0m"
            read -n 1 -r REPLY
            echo
            if [[ "$REPLY" =~ ^[Yy]$ ]]; then
                cp "$latest" "$md_file"
                echo -e "\033[32mRestored: $md_file\033[0m"
            fi
        else
            echo -e "\033[32m$md_file is already up to date.\033[0m"
        fi
    else
        cp "$latest" "$md_file"
        echo -e "\033[32mRestored: $md_file\033[0m"
    fi
}

restore_plugin() {
    local type="$1"
    echo -e "\n\033[34m>>> Processing Plugin ($type)\033[0m"
    
    local latest=$(ls -t "$STORAGE_DIR"/*_"${type}_PLUGIN"* 2>/dev/null | grep -E "[0-9]{8}_[0-9]{6}_${type}_PLUGIN(\..*)?$" | head -1)
    if [[ -z "$latest" ]]; then
        echo -e "\033[31mError: Stored plugin not found for type $type\033[0m"
        return
    fi

    local filename_ext=$(basename "$latest")
    local ext="${filename_ext##*.}"
    local plugin_name
    if [[ "$ext" == "$filename_ext" ]]; then
        plugin_name="$type"
    else
        plugin_name="$type.$ext"
    fi
    local target="$PLUGINS_DIR/$plugin_name"

    mkdir -p "$PLUGINS_DIR"

    if [[ -f "$target" ]]; then
        if ! diff -q "$target" "$latest" > /dev/null; then
            echo "Differences found in $plugin_name:"
            compare_files "$target" "$latest"
            echo -n -e "\033[33mOverwrite $target? (y/N) \033[0m"
            read -n 1 -r REPLY
            echo
            if [[ "$REPLY" =~ ^[Yy]$ ]]; then
                cp "$latest" "$target"
                echo -e "\033[32mRestored: $target\033[0m"
            fi
        else
            echo -e "\033[32m$target is already up to date.\033[0m"
        fi
    else
        cp "$latest" "$target"
        echo -e "\033[32mRestored: $target\033[0m"
    fi
}

restore_skill() {
    local type="$1"
    echo -e "\n\033[34m>>> Processing Skill ($type)\033[0m"
    
    local latest=$(ls -t "$STORAGE_DIR"/*"${type}_SKILL.tar.gz" 2>/dev/null | head -1)
    if [[ -z "$latest" ]]; then
        echo -e "\033[31mError: Stored skill archive not found for type $type\033[0m"
        return
    fi

    # Determine skill name from archive
    local skill_name=$(tar -tzf "$latest" | head -1 | sed 's|^/||' | sed 's|/.*||')
    local target_dir="$SKILLS_DIR/$skill_name"

    mkdir -p "$SKILLS_DIR"

    if [[ -d "$target_dir" ]]; then
        echo -e "\033[33mTarget directory $target_dir exists. Comparing...\033[0m"
        local temp_dir=$(mktemp -d)
        tar -xzf "$latest" -C "$temp_dir" --exclude="*undo-tree~"
        local extracted_dir="$temp_dir/$skill_name"

        # Comparison logic from fileskill_restore
        local diff_found=0
        find "$target_dir" -type f ! -name "*undo-tree~" -printf "%P\n" | sort > "$temp_dir/local.txt"
        find "$extracted_dir" -type f ! -name "*undo-tree~" -printf "%P\n" | sort > "$temp_dir/archive.txt"
        
        while IFS= read -r file; do
            local_file="$target_dir/$file"
            archive_file="$extracted_dir/$file"
            if [[ -f "$local_file" && -f "$archive_file" ]]; then
                if [[ $(stat -c%s "$local_file") -ne $(stat -c%s "$archive_file") ]]; then
                    echo -e "  \033[31m$file (DIFFERENT SIZE)\033[0m"
                    diff_found=1
                fi
            elif [[ -f "$local_file" ]]; then
                echo -e "  \033[31m$file (Missing in archive)\033[0m"
                diff_found=1
            else
                echo -e "  \033[32m$file (New in archive)\033[0m"
                diff_found=1
            fi
        done < <(cat "$temp_dir/local.txt" "$temp_dir/archive.txt" | sort -u)

        if [[ $diff_found -eq 0 ]]; then
            echo -e "\033[32mNo differences found.\033[0m"
        fi

        echo -n -e "\033[33mOverwrite directory $target_dir? (y/N) \033[0m"
        read -n 1 -r REPLY
        echo
        rm -rf "$temp_dir"
        if [[ ! "$REPLY" =~ ^[Yy]$ ]]; then
            echo "Skipped $type"
            return
        fi
        rm -rf "$target_dir"
    fi

    tar -xzf "$latest" -C "$SKILLS_DIR" --exclude="*undo-tree~"
    echo -e "\033[32mRestored skill to: $target_dir\033[0m"
}

restore_subagent() {
    local type="$1"
    echo -e "\n\033[34m>>> Processing Subagent ($type)\033[0m"
    
    local latest=$(ls -t "$STORAGE_DIR"/*"${type}_SUBAGENT.md" 2>/dev/null | head -1)
    if [[ -z "$latest" ]]; then
        echo -e "\033[31mError: Stored subagent not found for type $type\033[0m"
        return
    fi

    local target="$AGENTS_DIR/${type}.md"

    mkdir -p "$AGENTS_DIR"

    if [[ -f "$target" ]]; then
        if ! diff -q "$target" "$latest" > /dev/null; then
            echo "Differences found in ${type}.md:"
            compare_files "$target" "$latest"
            echo -n -e "\033[33mOverwrite $target? (y/N) \033[0m"
            read -n 1 -r REPLY
            echo
            if [[ "$REPLY" =~ ^[Yy]$ ]]; then
                cp "$latest" "$target"
                echo -e "\033[32mRestored: $target\033[0m"
            fi
        else
            echo -e "\033[32m$target is already up to date.\033[0m"
        fi
    else
        cp "$latest" "$target"
        echo -e "\033[32mRestored: $target\033[0m"
    fi
}

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 ${#PLUGIN_TYPES[@]} ]]; then
                type="${PLUGIN_TYPES[$idx]}"
                tdesc="${TYPE_DESCRIPTIONS["PLUGIN:${type}"]}"
                LAST_DESC=$([[ -n "$tdesc" ]] && echo "${type}: ${tdesc}" || echo "")
                if [[ "${SELECTED_PLUGINS[$type]}" == "1" ]]; then
                    unset SELECTED_PLUGINS["$type"]
                else
                    SELECTED_PLUGINS["$type"]="1"
                fi
            fi
            ;;
        [j-r])
            printf -v idx "%d" "'${input:0:1}"
            idx=$((idx - 106))
            if [[ $idx -lt ${#SKILL_TYPES[@]} ]]; then
                type="${SKILL_TYPES[$idx]}"
                tdesc="${TYPE_DESCRIPTIONS["SKILL:${type}"]}"
                LAST_DESC=$([[ -n "$tdesc" ]] && echo "${type}: ${tdesc}" || echo "")
                if [[ "${SELECTED_SKILLS[$type]}" == "1" ]]; then
                    unset SELECTED_SKILLS["$type"]
                else
                    SELECTED_SKILLS["$type"]="1"
                fi
            fi
            ;;
        [s-z])
            printf -v idx "%d" "'${input:0:1}"
            idx=$((idx - 115))
            if [[ $idx -lt ${#SUBAGENT_TYPES[@]} ]]; then
                type="${SUBAGENT_TYPES[$idx]}"
                tdesc="${TYPE_DESCRIPTIONS["SUBAGENT:${type}"]}"
                LAST_DESC=$([[ -n "$tdesc" ]] && echo "${type}: ${tdesc}" || echo "")
                if [[ "${SELECTED_SUBAGENTS[$type]}" == "1" ]]; then
                    unset SELECTED_SUBAGENTS["$type"]
                else
                    SELECTED_SUBAGENTS["$type"]="1"
                fi
            fi
            ;;
        *)
            if [[ "$input" =~ ^[0-9]+$ ]] && [[ "$input" -ne 10 ]] && [[ "$input" -ge 1 ]]; then
                idx=$(_disp2idx "$input")
                if [[ $idx -ge 0 ]] && [[ $idx -lt ${#AGENT_TYPES[@]} ]]; then
                    type="${AGENT_TYPES[$idx]}"
                    tdesc="${TYPE_DESCRIPTIONS["AGENTS.md:${type}"]}"
                    LAST_DESC=$([[ -n "$tdesc" ]] && echo "${type}: ${tdesc}" || echo "")
                    if [[ "$SELECTED_AGENT" == "$type" ]]; then
                        SELECTED_AGENT=""
                    else
                        SELECTED_AGENT="$type"
                    fi
                fi
            fi
            ;;
    esac
done

# --- Execute Restorations ---

if [[ -n "$SELECTED_AGENT" ]]; then
    restore_agent "$SELECTED_AGENT"
fi

for type in "${!SELECTED_PLUGINS[@]}"; do
    restore_plugin "$type"
done

for type in "${!SELECTED_SKILLS[@]}"; do
    restore_skill "$type"
done

for type in "${!SELECTED_SUBAGENTS[@]}"; do
    restore_subagent "$type"
done

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