package linuxmodules

import (
	"rubric/utils"
)

var BackupModule = Module{
	Key:         "backup",
	Aliases:     []string{"bk", "tar", "бэкап"},
	Title:       "Резервное копирование",
	Description: "Темы 38–40: tar, инкрементальные бэкапы, rsync, VDO",
	Run:         showBackup,
}

func showBackup() {
	utils.Header("Linux — Резервное копирование")

	// ─── 38. tar ──────────────────────────────────────────────────
	utils.Section("38. Создание бэкапов с tar")

	utils.Println("tar — основной инструмент архивирования в Linux.")
	utils.Println(utils.ColorBold + "\nОсновные флаги tar:" + utils.ColorReset)
	utils.Code(`c   — create    (создать архив)
x   — extract  (извлечь)
t   — list     (показать содержимое)
v   — verbose  (подробный вывод)
f   — file     (имя файла архива)
z   — gzip     (сжатие gzip, .tar.gz / .tgz)
j   — bzip2    (сжатие bzip2, .tar.bz2)
J   — xz       (сжатие xz, .tar.xz)
p   — preserve permissions (сохранить права)
C   — change directory (распаковать в указанную папку)`)

	utils.Println(utils.ColorBold + "Создание архива:" + utils.ColorReset)
	utils.Code(`# Создать архив:
tar -cvf archive.tar /path/to/dir      # без сжатия
tar -czvf archive.tar.gz /etc/         # с gzip
tar -cjvf archive.tar.bz2 /var/www/   # с bzip2
tar -cJvf archive.tar.xz /home/alice/ # с xz (медленнее, лучше)

# Создать с меткой даты:
tar -czvf backup_$(date +%Y%m%d_%H%M).tar.gz /etc/

# Исключить директории:
tar -czvf backup.tar.gz /home/ \
    --exclude=/home/.cache \
    --exclude='/home/*/.local'

# Архивировать только изменённые файлы:
tar -czvf backup.tar.gz --newer "2024-01-01" /home/`)

	utils.Println(utils.ColorBold + "Извлечение архива:" + utils.ColorReset)
	utils.Code(`# Извлечь в текущую директорию:
tar -xvf archive.tar
tar -xzvf archive.tar.gz

# Извлечь в указанную директорию:
tar -xzvf archive.tar.gz -C /tmp/restore/

# Извлечь только конкретные файлы:
tar -xzvf archive.tar.gz etc/nginx/nginx.conf

# Просмотр содержимого без распаковки:
tar -tzvf archive.tar.gz
tar -tzvf archive.tar.gz | grep nginx`)

	utils.Println(utils.ColorBold + "rsync — синхронизация файлов:" + utils.ColorReset)
	utils.Code(`# Базовый синтаксис: rsync [опции] источник назначение

# Опции:
-a   — архивный режим (-rlptgoD: рекурсия, права, время...)
-v   — verbose
-z   — сжатие при передаче
-P   — прогресс + продолжение
-n   — dry-run (симуляция без изменений)
--delete  — удалять файлы которых нет в источнике
-e ssh    — использовать SSH

# Локальная синхронизация:
rsync -av /source/ /dest/       # / после source — содержимое (без самой папки)
rsync -av /source /dest/        # без / — копирует саму папку

# По сети через SSH:
rsync -avzP /home/alice/ user@server:/backup/alice/
rsync -avzP user@server:/data/ /local/backup/

# Зеркало (с удалением лишнего):
rsync -av --delete /source/ /mirror/

# Бэкап с сохранением удалённых файлов:
rsync -av --backup --backup-dir=/backup/old-$(date +%Y%m%d) \
    --delete /source/ /mirror/`)

	// ─── 39. Инкрементальные бэкапы ───────────────────────────────
	utils.Section("39. Инкрементальные бэкапы с tar")

	utils.Println("Инкрементальный бэкап — сохраняет только изменения с момента последнего бэкапа.")
	utils.Code(`# tar поддерживает инкрементальные бэкапы через snapshot-файл.
# Snapshot хранит список файлов и время последнего изменения.

# Полный бэкап (level 0):
tar -czvf backup_full_$(date +%Y%m%d).tar.gz \
    --listed-incremental=/var/backup/snapshot.snar \
    /home/

# Инкрементальный бэкап (только изменения):
tar -czvf backup_incr_$(date +%Y%m%d_%H%M).tar.gz \
    --listed-incremental=/var/backup/snapshot.snar \
    /home/

# Восстановление: сначала полный, затем все инкрементальные по порядку:
tar -xzvf backup_full_20240101.tar.gz \
    --listed-incremental=/dev/null -C /restore/
tar -xzvf backup_incr_20240102.tar.gz \
    --listed-incremental=/dev/null -C /restore/

# Просмотр инкрементального архива:
tar -tzvf backup_incr.tar.gz --listed-incremental=/dev/null`)

	utils.Println(utils.ColorBold + "Скрипт автоматического бэкапа:" + utils.ColorReset)
	utils.Code(`#!/bin/bash
set -euo pipefail

BACKUP_DIR="/backup"
SOURCE="/home /etc /var/www"
SNAPSHOT="/var/backup/snapshot.snar"
DATE=$(date +%Y%m%d_%H%M)
LOG="/var/log/backup.log"

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG"; }

log "Начало бэкапа"

# Полный бэкап по воскресеньям, инкрементальный остальные дни:
if [ "$(date +%u)" -eq 7 ]; then
    cp "$SNAPSHOT" "${SNAPSHOT}.prev" 2>/dev/null || true
    ARCHIVE="$BACKUP_DIR/full_$DATE.tar.gz"
    tar -czvf "$ARCHIVE" --listed-incremental="$SNAPSHOT" $SOURCE
    log "Полный бэкап: $ARCHIVE"
else
    ARCHIVE="$BACKUP_DIR/incr_$DATE.tar.gz"
    tar -czvf "$ARCHIVE" --listed-incremental="$SNAPSHOT" $SOURCE
    log "Инкрементальный бэкап: $ARCHIVE"
fi

# Удалить старые бэкапы (оставить за 30 дней):
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +30 -delete
log "Старые бэкапы очищены. Готово."`)

	// ─── 40. VDO ──────────────────────────────────────────────────
	utils.Section("40. Дедупликация с VDO (Virtual Data Optimizer)")

	utils.Println("VDO — технология RHEL для дедупликации и сжатия данных на блочном уровне.")
	utils.Println("Уменьшает занимаемое место на диске без изменения работы приложений.")
	utils.Code(`# VDO доступен в RHEL/CentOS. Установка:
dnf install vdo kmod-kvdo

# Создать VDO-устройство поверх блочного (/dev/sdb):
vdo create --name=vdo_data \
    --device=/dev/sdb \
    --vdoLogicalSize=100G    # виртуальный размер (больше физического)

# Посмотреть VDO-устройства:
vdo list
vdo status --name=vdo_data

# Создать ФС на VDO:
mkfs.ext4 -E nodiscard /dev/mapper/vdo_data
mount /dev/mapper/vdo_data /mnt/data

# Статистика экономии:
vdostats --human-readable
# Показывает: физический размер / использовано / коэффициент сжатия

# VDO в /etc/fstab:
/dev/mapper/vdo_data  /mnt/data  ext4  defaults,x-systemd.requires=vdo.service  0 2

# Запустить/остановить:
vdo start --name=vdo_data
vdo stop --name=vdo_data

# Удалить VDO:
vdo remove --name=vdo_data --force`)

	utils.Note("VDO хорошо работает для виртуализации, контейнеров и бэкапов — там много одинаковых данных.")
	utils.Note("LVM 2.3+ поддерживает VDO напрямую через lvcreate --type vdo.")

	utils.Footer()
}
