#!/usr/bin/env bash

set -euo pipefail

# --- НАСТРОЙКИ ---

# Разрешенная базовая версия ядра (например, "6.12" или "6.18")
# Оставьте пустой "", если нужно искать абсолютно любое самое новое ядро выбранного суффикса
ALLOWED_BRANCH="6.12"

KERNEL_SUFFIX="darkness"
MIRROR_URL="http://10.100.10.31:9090/kernel"
SRC_DIR="/usr/src"
BOOT_DIR="/boot"
LIB_MODULES_DIR="/lib/modules"
GRUB_CFG="/boot/grub/grub.cfg"
LILO_CONF="/boot/lilo.conf"
LILO_BIN="/boot/lilo"


echo ">>> Шаг 1-2: Запрос списка ядер и поиск последней версии -${KERNEL_SUFFIX}..."

# Формируем паттерн для grep в зависимости от указанной версии ветки
if [ -n "${ALLOWED_BRANCH}" ]; then
    # Экранируем точку в версии, превращая "6.12" в "6\.12" для регулярного выражения
    REGEX_BRANCH=$(echo "${ALLOWED_BRANCH}" | sed 's/\./\\./g')
    GREP_PATTERN="linux-${REGEX_BRANCH}\.[0-9]+-${KERNEL_SUFFIX}-kbuild\.tar\.zst"
else
    GREP_PATTERN="linux-[0-9]+\.[0-9]+\.[0-9]+-${KERNEL_SUFFIX}-kbuild\.tar\.zst"
fi

LATEST_TARBALL=$(curl -sSL "${MIRROR_URL}" | \
    grep -oE "${GREP_PATTERN}" | \
    sort -V | \
    tail -n1)

if [ -z "${LATEST_TARBALL}" ]; then
    echo "Ошибка: Не удалось найти архивы ядер ветки '${ALLOWED_BRANCH:-любая}' с суффиксом -${KERNEL_SUFFIX}-kbuild." >&2
    exit 1
fi

NEW_KERNEL_NAME=$(basename "${LATEST_TARBALL}" "-kbuild.tar.zst")
NEW_KERNEL_VERSION=$(echo "${NEW_KERNEL_NAME}" | sed 's/linux-//')

echo "Найдено последнее доступное ядро: ${NEW_KERNEL_NAME}"

if [ -d "${SRC_DIR}/${NEW_KERNEL_NAME}" ] && [ -L "${SRC_DIR}/linux" ] && [ "$(readlink "${SRC_DIR}/linux")" = "${NEW_KERNEL_NAME}" ]; then
    echo "Ядро версии ${NEW_KERNEL_VERSION} уже установлено и активно. Обновление не требуется."
    exit 0
fi

cd "${SRC_DIR}"

echo ">>> Шаг 3: Удаление старой символьной ссылки и дерева источников..."
if [ -L "linux" ]; then
    OLD_DIR=$(readlink "linux")
    echo "Удаляем старую ссылку 'linux' и папку источника '${OLD_DIR}'..."
    rm -f "linux"
    if [ -d "${OLD_DIR}" ] && [ "${OLD_DIR}" != "/" ]; then
        rm -rf "${OLD_DIR}"
    fi
fi

echo ">>> Шаг 4: Скачивание и распаковка нового kbuild-дерева..."
curl -sSL "${MIRROR_URL}/${LATEST_TARBALL}" | zstd -dcv | tar -xf -

echo ">>> Шаг 5: Создание симлинка и очистка дерева (make clean)..."
ln -snf "${NEW_KERNEL_NAME}" linux
cd linux
make clean

echo ">>> Шаг 6: Поиск и распаковка вложенного архива модулей и boot-файлов..."
# Ищем архив модулей, динамически подставляя текущий суффикс ядра
LZMA_ARCHIVE=$(ls linux-*-${KERNEL_SUFFIX}-x86.tar.lzma 2>/dev/null | head -n1)

if [ -z "${LZMA_ARCHIVE}" ]; then
    echo "Ошибка: Внутри дерева не найден архив модулей *--${KERNEL_SUFFIX}-x86.tar.lzma" >&2
    exit 1
fi

TMP_INSTALL=$(mktemp -d /tmp/kernel-install.XXXXXX)

# Распаковываем архив во временный каталог
tar --lzma -xf "${LZMA_ARCHIVE}" -C "${TMP_INSTALL}"

# Ищем папки boot и lib/modules на любой глубине
BOOT_SRC=$(find "${TMP_INSTALL}" -type d -name "boot" -print -quit)
LIB_SRC=$(find "${TMP_INSTALL}" -type d -path "*/lib/modules" -print -quit)

if [ -n "${BOOT_SRC}" ] && [ -d "${BOOT_SRC}" ]; then
    # Определяем точное имя бинарника ядра (например, vmlinuz-6.12.15-darkness)
    REAL_VMLINUZ=$(find "${BOOT_SRC}" -type f -name "vmlinuz-*" -exec basename {} \; -quit)
    
    echo "Копируем файлы ядра в ${BOOT_DIR}..."
    cp -af "${BOOT_SRC}/". "${BOOT_DIR}/"
else
    echo "Ошибка: Папка boot не найдена внутри архива!" >&2
    exit 1
fi

if [ -n "${LIB_SRC}" ] && [ -d "${LIB_SRC}" ]; then
    echo "Копируем модули в ${LIB_MODULES_DIR}..."
    cp -af "${LIB_SRC}/". "${LIB_MODULES_DIR}/"
else
    echo "Ошибка: Папка lib/modules не найдена внутри архива!" >&2
    exit 1
fi

rm -rf "${TMP_INSTALL}"

echo ">>> Шаг 7: Выполнение depmod для нового релиза (${NEW_KERNEL_VERSION})..."
depmod -a "${NEW_KERNEL_VERSION}"

echo ">>> Шаг 8: Обновление конфигурации загрузчика..."

# --- ЛОГИКА ДЛЯ LILO ---
if [ -f "${LILO_CONF}" ]; then
    echo "Обнаружен LILO (${LILO_CONF}). Настройка ссылок..."
    
    # 1) Перемещение старой ссылки /boot/vmlinuz в /boot/vmlinuz.old
    if [ -L "${BOOT_DIR}/vmlinuz" ] || [ -f "${BOOT_DIR}/vmlinuz" ]; then
        echo "Перемещаем старый vmlinuz в vmlinuz.old..."
        mv -f "${BOOT_DIR}/vmlinuz" "${BOOT_DIR}/vmlinuz.old"
    fi
    
    # 2) Создание ссылки с нового ядра на vmlinuz
    if [ -n "${REAL_VMLINUZ:-}" ] && [ -f "${BOOT_DIR}/${REAL_VMLINUZ}" ]; then
        echo "Создаем симлинк vmlinuz -> ${REAL_VMLINUZ}..."
        ln -snf "${REAL_VMLINUZ}" "${BOOT_DIR}/vmlinuz"
    else
        echo "Ошибка: Не удалось найти скопированное ядро ${REAL_VMLINUZ:-} в ${BOOT_DIR}" >&2
        exit 1
    fi
    
    # 3) Вызов /boot/lilo
    if [ -x "${LILO_BIN}" ]; then
        echo "Запуск LILO из ${LILO_BIN}..."
        "${LILO_BIN}"
        echo ">>> Обновление ядра под LILO успешно завершено! Можно перезагружаться."
    else
        echo "Ошибка: Исполняемый файл LILO не найден по пути ${LILO_BIN}!" >&2
        exit 1
    fi

# --- ЛОГИКА ДЛЯ GRUB ---
elif command -v grub-mkconfig >/dev/null 2>&1; then
    echo "Обнаружен GRUB. Обновление конфигурации..."
    grub-mkconfig -o "${GRUB_CFG}"
    echo ">>> Обновление ядра под GRUB успешно завершено! Можно перезагружаться."
else
    echo "Ошибка: Не найден ни ${LILO_CONF}, ни утилита grub-mkconfig!" >&2
    exit 1
fi
