#!/bin/bash

VIRT_IP="192.168.122.116"
SSH_CMD="ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null linadmin@$VIRT_IP"
BASE_DIR="/home/linadmin/domain_build"
LOG_FILE="${BASE_DIR}/build.log"
VM_NAME="debian11"
DEVICE_PATH="/dev/nvme0n1p6"
VG_NAME="astra95067"

mkdir -p "$BASE_DIR"

echo "Начало сборки образа: $(date)" | tee "$LOG_FILE"

STEPS=(
    "step_01_prepare_system_for_image"
    "step_02_shutdown_vm"
    "step_03_create_archive"
)

step_01_prepare_system_for_image() {
  echo "=== Шаг 1: Подготовка системы для образа ===" | tee -a "$LOG_FILE"
  $SSH_CMD "sudo apt install -y cifs-utils keyutils sssd sssd-tools realmd adcli krb5-user puppet autofs python3-apt dialog whiptail \
    fly-notifications astra-kvm ovmf dialog python3-tk python3-termcolour" \
    && echo "$(date +%T) Базовый софт установлен" | tee -a "$LOG_FILE"
  $SSH_CMD "sudo apt install -y evolution evolution-ews evolution-plugins evolution-plugin-pstimport yandex-browser-stable" \
    && echo "$(date +%T) Кастомный софт установлен" | tee -a "$LOG_FILE"
  $SSH_CMD "sudo apt install -y libreoffice-math libreoffice-calc libreoffice-impress libreoffice-draw libreoffice-writer" \
    && echo "$(date +%T) libre офис установлен" | tee -a "$LOG_FILE"
  $SSH_CMD "sudo mkdir -p /home/image_prepare/ | sudo chmod -R 777 /home/image_prepare/"
  scp "prepare_files/sssd.conf" linadmin@$VIRT_IP:/home/image_prepare/ \
    && $SSH_CMD "cat /home/image_prepare/sssd.conf | sudo tee /etc/sssd/sssd.conf" | tee -a "$LOG_FILE"
  scp "prepare_files/krb5.conf" linadmin@$VIRT_IP:/home/image_prepare/ \
    && $SSH_CMD "cat /home/image_prepare/krb5.conf | sudo tee /etc/krb5.conf" | tee -a "$LOG_FILE"
  scp "prepare_files/skel_profile.conf" linadmin@$VIRT_IP:/home/image_prepare/ \
    && $SSH_CMD "cat /home/image_prepare/skel_profile.conf | sudo tee /etc/skel/.profile" | tee -a "$LOG_FILE"
  scp "prepare_files/admin-helper.bin" linadmin@$VIRT_IP:/home/image_prepare/ \
    && $SSH_CMD "sudo mv /home/image_prepare/admin-helper.bin /root/" | tee -a "$LOG_FILE"
  $SSH_CMD "sudo chmod +x /root/admin-helper.bin" | tee -a "$LOG_FILE"
  scp "prepare_files/grub_default.conf" linadmin@$VIRT_IP:/home/image_prepare/ \
    && $SSH_CMD "cat /home/image_prepare/grub_default.conf | sudo tee /etc/default/grub" | tee -a "$LOG_FILE"
  $SSH_CMD "echo | sudo tee /etc/initramfs-tools/conf.d/resume" | tee -a "$LOG_FILE"
  $SSH_CMD "sudo update-initramfs -u -k all" | tee -a "$LOG_FILE"
  $SSH_CMD "sudo update-grub" | tee -a "$LOG_FILE"
  $SSH_CMD "sudo virsh net-autostart default"| tee -a "$LOG_FILE"
  echo "=== Шаг 1: Завершен ===" | tee -a "$LOG_FILE"
}

step_02_shutdown_vm() {
  echo "=== Шаг 2: Выключение виртуальной машины ===" | tee -a "$LOG_FILE"  
  echo "$(date +%T) Выполняется выключение ВМ через SSH..." | tee -a "$LOG_FILE"
  $SSH_CMD "sudo poweroff" | tee -a "$LOG_FILE"
    EXIT_CODE=${PIPESTATUS[0]}
    if [[ $EXIT_CODE -ne 0 ]]; then
        echo "$(date +%T) Предупреждение: SSH команда завершилась с кодом $EXIT_CODE (возможно, соединение разорвано при выключении)" | tee -a "$LOG_FILE"
    fi
    echo "Ожидание полного выключения ВМ..." | tee -a "$LOG_FILE"
    local max_attempts=30
    local attempt=1
    while [[ $attempt -le $max_attempts ]]; do
      echo "Проверка состояния ВМ (попытка $attempt/$max_attempts)..." | tee -a "$LOG_FILE"
      if ! sudo LANG=C virsh list --all | grep -q "$VM_NAME"; then
        echo "ОШИБКА: ВМ '$VM_NAME' не найдена в virsh list" | tee -a "$LOG_FILE"
        exit 1
      fi        
      if sudo LANG=C virsh list --state-shutoff | grep -q "$VM_NAME"; then
        echo "$(date +%T) ВМ успешно выключена" | tee -a "$LOG_FILE"
        break
      fi  
      if [[ $attempt -eq $max_attempts ]]; then
        echo "ОШИБКА: ВМ не выключилась за $max_attempts попыток" | tee -a "$LOG_FILE"
        exit 1
      fi
      sleep 5
      ((attempt++))
    done
    echo "=== Шаг 2 завершен успешно ===" | tee -a "$LOG_FILE"
}

step_03_create_archive() {
  echo "=== Шаг 3: Создание архива образа ===" | tee -a "$LOG_FILE"
  cd "$BASE_DIR"
  MOUNT_DIR="${BASE_DIR}/part_mount"
  ARCHIVE_PATH="${BASE_DIR}/obraz.tar.bz2"

  mkdir -p "$MOUNT_DIR"

  echo "$(date +%T) Монтируем устройство..." | tee -a "$LOG_FILE"
  sudo kpartx -a "$DEVICE_PATH" 2>&1 | tee -a "$LOG_FILE"
  if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
    echo "$(date +%T) OШИБКА: Ошибка монтирования kpartx" | tee -a "$LOG_FILE"
    exit 1
  fi
  sudo vgscan --config "devices { use_devicesfile = 0 }" 2>&1 | tee -a "$LOG_FILE"
  sudo vgchange -ay "$VG_NAME" --devicesfile "" 2>&1 | tee -a "$LOG_FILE"
  if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
      echo "$(date +%T) ОШИБКА: Ошибка активации LVM" | tee -a "$LOG_FILE"
      sudo kpartx -d "$DEVICE_PATH"
      exit 1
  fi
  if [[ ! -d "$MOUNT_DIR" ]]; then
      echo "$(date +%T) Создаем точку монтирования..." | tee -a "$LOG_FILE"
      mkdir -p "$MOUNT_DIR" 2>&1 | tee -a "$LOG_FILE"
  fi
  echo "$(date +%T) Монтируем раздел..." | tee -a "$LOG_FILE"
  sudo mount "/dev/${VG_NAME}/lv_root" "$MOUNT_DIR/" 2>&1 | tee -a "$LOG_FILE"
  if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
      echo "$(date +%T) ОШИБКА: Ошибка монтирования раздела" | tee -a "$LOG_FILE"
      sudo vgchange -an "$VG_NAME" --devicesfile ""
      sudo kpartx -d "$DEVICE_PATH"
      exit 1
  fi
  echo "$(date +%T) Создаем архив..." | tee -a "$LOG_FILE"
  SIZE_BYTES=$(sudo du -sb "$MOUNT_DIR" | cut -f1)
  
  if sudo tar cf - --preserve-permissions --same-owner --acls --xattrs -C "$MOUNT_DIR" . | bzip2 > "$ARCHIVE_PATH"; then
      echo "$(date +%T) Архив успешно создан" | tee -a "$LOG_FILE"
      if [[ -f "$ARCHIVE_PATH" ]]; then
          ARCHIVE_SIZE=$(du -h "$ARCHIVE_PATH" | cut -f1)
          echo "Размер архива: $ARCHIVE_SIZE" | tee -a "$LOG_FILE"
      fi
  else
      echo "$(date +%T) ОШИБКА: Создание архива" | tee -a "$LOG_FILE"
      sudo umount "$MOUNT_DIR/"
      sudo vgchange -an "$VG_NAME" --devicesfile ""
      sudo kpartx -d "$DEVICE_PATH"
      exit 1
  fi
  echo "Размонтируем..." | tee -a "$LOG_FILE"
  sudo umount "$MOUNT_DIR/" 2>&1 | tee -a "$LOG_FILE"
  sudo vgchange -an "$VG_NAME" --devicesfile "" 2>&1 | tee -a "$LOG_FILE"
  echo "Очищаем mapping..." | tee -a "$LOG_FILE"
  sudo kpartx -d "$DEVICE_PATH" 2>&1 | tee -a "$LOG_FILE"
  echo "$(date +%T)"
  rm -rf "$MOUNT_DIR"
  echo "🔄 Конвертация образа из tar.bz2 в tar.zst"
  TEMP_DIR=$(mktemp -d)
  echo "📁 Временная папка: $TEMP_DIR"
  echo "📦 Распаковка tar.bz2..."
  if tar -xjf "$ARCHIVE_PATH" -C "$TEMP_DIR"; then
      echo "✅ Распаковка успешно завершена"
      
      echo "🔨 Упаковка в zstd (используем все ядра)..."
      if tar --help | grep -q zstd; then
          tar -C "$TEMP_DIR" -cf "$BASE_DIR/obraz.tar.zst" --zstd .
      else
          tar -C "$TEMP_DIR" -cf - . | zstd -T0 -19 -o "$BASE_DIR/obraz.tar.zst"
      fi
      
      if [[ $? -eq 0 ]]; then
          echo "✅ Архив образ.tar.zst успешно создан"
          ls -lh "$BASE_DIR/obraz.tar.zst"
      else
          echo "❌ Ошибка при создании архива zstd"
          exit 1
      fi
  else
      echo "❌ Ошибка при распаковке $ARCHIVE_PATH"
      exit 1
  fi
  rm "$ARCHIVE_PATH"
  rm -rf "$TEMP_DIR"
  echo "=== Шаг 3 завершен успешно ===" | tee -a "$LOG_FILE"
}

for step in "${STEPS[@]}"; do
    if declare -f "$step" > /dev/null; then
        "$step"
    else
        echo "ОШИБКА: Функция $step не определена" | tee -a "$LOG_FILE"
        exit 1
    fi
done

echo "Сборка образа завершена: $(date)" | tee -a "$LOG_FILE"