#!/usr/bin/env bash
# clean-system — безопасная интерактивная очистка системы

set -euo pipefail

_size() {
    du -sh "$1" 2>/dev/null | cut -f1 || echo "0"
}

_freed() {
    local before=$1 after=$2
    # оба в байтах через numfmt
    local b a
    b=$(numfmt --from=iec "$before" 2>/dev/null || echo 0)
    a=$(numfmt --from=iec "$after"  2>/dev/null || echo 0)
    local diff=$(( b - a ))
    (( diff > 0 )) && numfmt --to=iec "$diff" || echo "0"
}

# ── Задачи очистки ───────────────────────────────────────────
# Формат: "id|описание|команда|путь_для_размера"

declare -A TASK_CMD TASK_PATH TASK_DESC

_register() {
    local id=$1 desc=$2 path=$3; shift 3
    TASK_DESC[$id]="$desc"
    TASK_PATH[$id]="$path"
    TASK_CMD[$id]="$*"
}

_register pacman-cache \
    "Pacman кеш (оставить 2 версии)" \
    "/var/cache/pacman/pkg" \
    sudo paccache -rk2

_register paru-cache \
    "Paru build кеш" \
    "$HOME/.cache/paru" \
    paru -Sc --noconfirm

_register uv-cache \
    "uv (Python) кеш" \
    "$HOME/.cache/uv" \
    uv cache clean

_register npm-cache \
    "npm кеш" \
    "$HOME/.npm" \
    npm cache clean --force

_register cargo-cache \
    "Cargo registry (скачанные крейты)" \
    "$HOME/.cargo/registry" \
    rm -rf "$HOME/.cargo/registry/cache" "$HOME/.cargo/registry/src"

_register restic-cache \
    "Restic старые кеши" \
    "$HOME/.cache/restic" \
    restic cache --cleanup

_register thumbnails \
    "Кеш миниатюр" \
    "$HOME/.cache/thumbnails" \
    rm -rf "$HOME/.cache/thumbnails"

_register journal \
    "Systemd journal (оставить 2 недели)" \
    "" \
    journalctl --vacuum-time=2weeks

_register pip-cache \
    "pip кеш" \
    "$HOME/.cache/pip" \
    pip3 cache purge

_register zsh-compdump \
    "Zsh completion cache (пересоздастся автоматически)" \
    "" \
    bash -c 'rm -f "$HOME"/.config/zsh/.zcompdump*'

# ── Построение меню ──────────────────────────────────────────

main() {
    if ! command -v fzf &>/dev/null; then
        echo "fzf not found"
        exit 1
    fi

    local ORDERED=(pacman-cache paru-cache uv-cache npm-cache cargo-cache
                   restic-cache thumbnails journal pip-cache zsh-compdump)

    local lines=()
    for id in "${ORDERED[@]}"; do
        local size=""
        local path="${TASK_PATH[$id]}"
        if [[ -n "$path" && ( -d "$path" || -f "$path" ) ]]; then
            size=$(_size "$path")
        else
            size="—"
        fi
        lines+=("$(printf "%-14s  %6s   %s" "$id" "$size" "${TASK_DESC[$id]}")")
    done

    local selected
    selected=$(printf '%s\n' "${lines[@]}" | fzf \
        --multi \
        --prompt "clean > " \
        --header "Пробел — выбрать | Enter — запустить | Ctrl-A — выбрать всё" \
        --bind "ctrl-a:select-all" \
        --reverse \
        --height=50%) || exit 0

    [[ -z "$selected" ]] && exit 0

    local total_freed=0

    while IFS= read -r line; do
        local id
        id=$(echo "$line" | awk '{print $1}')
        local path="${TASK_PATH[$id]}"

        local before=""
        [[ -n "$path" && ( -d "$path" || -f "$path" ) ]] && before=$(_size "$path")

        echo ""
        echo "▶ ${TASK_DESC[$id]}"
        eval "${TASK_CMD[$id]}" || true

        if [[ -n "$path" && -n "$before" ]]; then
            local after
            after=$(_size "$path")
            local freed
            freed=$(_freed "$before" "$after")
            echo "  → освобождено: $freed"
        fi
    done <<< "$selected"

    echo ""
    echo "Готово."
}

main "$@"
