#!/usr/bin/env bash

# ============================================================
# Samba recycle cleanup
# Server: SMR-SRV-OT-SHARE
#
# Назначение:
#   Автоматическая очистка файлов из Samba .recycle
#   по времени их нахождения в корзине.
#
# В smb.conf используется:
#   recycle:touch_mtime = yes
#
# Поэтому mtime файла в .recycle соответствует моменту удаления
# через Samba и может использоваться для определения срока хранения.
#
# Политика хранения:
#   exchange         = 7 дней
#   pivoproduction   = 14 дней
#   rozliv           = 14 дней
#   utilities        = 14 дней
#   software         = 14 дней
#   documentation    = 30 дней
#   ot-admin          = 30 дней
#
# clonezilla не используется:
#   vfs_recycle для него намеренно отключён.
#
# Режимы:
#   --dry-run  только показать, что было бы удалено
#   --delete   реально удалить просроченные файлы
#
# Логирование выполняется через stdout/stderr.
# При запуске из systemd весь вывод попадает в journal.
# ============================================================

set -u
set -o pipefail


# ------------------------------------------------------------
# Базовый каталог Samba
# ------------------------------------------------------------

BASE="/srv/main-data/baltikashare"


# ------------------------------------------------------------
# Определение режима запуска
# ------------------------------------------------------------

MODE="${1:---dry-run}"

case "$MODE" in
    --dry-run)
        DELETE=false
        ;;
    --delete)
        DELETE=true
        ;;
    *)
        echo "Usage: $0 [--dry-run|--delete]"
        exit 2
        ;;
esac


# ------------------------------------------------------------
# Проверяем, что production-хранилище смонтировано.
#
# Это принципиально важно:
# скрипт не должен работать с каталогом на root filesystem,
# если MAIN-DATA по какой-либо причине не смонтирован.
# ------------------------------------------------------------

if ! mountpoint -q /srv/main-data; then
    echo "ERROR: /srv/main-data is not mounted."
    echo "Cleanup aborted."
    exit 1
fi


# ------------------------------------------------------------
# Проверяем Btrfs.
# ------------------------------------------------------------

FS_TYPE="$(findmnt -n -o FSTYPE /srv/main-data 2>/dev/null || true)"

if [[ "$FS_TYPE" != "btrfs" ]]; then
    echo "ERROR: /srv/main-data filesystem is '$FS_TYPE', expected 'btrfs'."
    echo "Cleanup aborted."
    exit 1
fi


# ------------------------------------------------------------
# Политика хранения.
#
# Формат:
#   share:days
# ------------------------------------------------------------

POLICY=(
    "exchange:7"
    "pivoproduction:14"
    "rozliv:14"
    "utilities:14"
    "software:14"
    "documentation:30"
    "ot-admin:30"
)


echo "============================================================"
echo "Samba recycle cleanup"
echo "Date: $(date '+%Y-%m-%d %H:%M:%S %z')"
echo "Mode: $MODE"
echo "============================================================"


TOTAL_FILES=0
TOTAL_BYTES=0


for ITEM in "${POLICY[@]}"; do

    SHARE="${ITEM%%:*}"
    DAYS="${ITEM##*:}"

    RECYCLE="${BASE}/${SHARE}/.recycle"

    echo
    echo "------------------------------------------------------------"
    echo "Share:     $SHARE"
    echo "Recycle:   $RECYCLE"
    echo "Retention: $DAYS days"
    echo "------------------------------------------------------------"


    # Если корзина ещё ни разу не создавалась — это не ошибка.
    if [[ ! -d "$RECYCLE" ]]; then
        echo "INFO: recycle directory does not exist, skipping."
        continue
    fi


    # Используем минуты вместо find -mtime.
    #
    # Это даёт более предсказуемый порог:
    # 7 дней  = 10080 минут
    # 14 дней = 20160 минут
    # 30 дней = 43200 минут.
    AGE_MINUTES=$((DAYS * 24 * 60))


    while IFS= read -r -d '' FILE; do

        SIZE="$(stat -c '%s' "$FILE" 2>/dev/null || echo 0)"

        TOTAL_FILES=$((TOTAL_FILES + 1))
        TOTAL_BYTES=$((TOTAL_BYTES + SIZE))

        if [[ "$DELETE" == true ]]; then
            echo "DELETE: $FILE"
            rm -f -- "$FILE"
        else
            echo "WOULD DELETE: $FILE"
        fi

    done < <(
        find "$RECYCLE" \
            -xdev \
            -type f \
            -mmin "+${AGE_MINUTES}" \
            -print0
    )


    # В режиме реального удаления очищаем оставшиеся пустые каталоги.
    #
    # Сам корневой каталог .recycle не удаляется.
    # Пользовательские каталоги при необходимости Samba создаст снова.
    if [[ "$DELETE" == true ]]; then

        find "$RECYCLE" \
            -xdev \
            -depth \
            -mindepth 1 \
            -type d \
            -empty \
            -delete
    fi

done


echo
echo "============================================================"
echo "Summary"
echo "============================================================"
echo "Matched files: $TOTAL_FILES"
echo "Matched bytes: $TOTAL_BYTES"

if command -v numfmt >/dev/null 2>&1; then
    echo "Matched size:  $(numfmt --to=iec-i --suffix=B "$TOTAL_BYTES")"
fi

if [[ "$DELETE" == true ]]; then
    echo "Result: expired files deleted."
else
    echo "Result: DRY-RUN only. Nothing was deleted."
fi

echo "Finished: $(date '+%Y-%m-%d %H:%M:%S %z')"
