#!/usr/bin/env bash
# ==============================================
#   Скрипт поэтапного обновления Astra Linux
# ==============================================
# Цвета
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
RESET='\033[0m'
# Иконки
CHECK="✅"
ERROR="❌"
WARN="⚠️"
INFO="ℹ️"
ARROW="➜"
ROCKET="🚀"

# Путь к маркер-файлу
MARKER_FILE="/opt/config/custom_update_status.info"
VERSION_FILE="/etc/astra/build_version"
TARGET_VERSION="1.7.10.72"

# ==============================================
# Функции работы с маркер-файлом
# ==============================================

init_marker() {
    mkdir -p "$(dirname "$MARKER_FILE")" 2>/dev/null    
    # Если файла нет - создаем со статусом 5
    if [[ ! -f "$MARKER_FILE" ]]; then
        echo "5" > "$MARKER_FILE"
        echo -e "${BLUE}${INFO} Создан маркер-файл: ${MARKER_FILE}${RESET}"
    fi
}

get_status() {
    if [[ -f "$MARKER_FILE" ]]; then
        cat "$MARKER_FILE" | tr -d ' \t\n\r'
    else
        echo "5"
    fi
}

set_status() {
    echo "$1" > "$MARKER_FILE"
    echo -e "${BLUE}${INFO} Статус обновления: ${BOLD}$1${RESET}"
}

show_status_info() {
    local status=$(get_status)
    echo -e "\n${BOLD}${CYAN}━━━ Статус обновления ━━━${RESET}"    
    case $status in
        1072)
            echo -e "${GREEN}${CHECK} Система актуальна (версия $CURRENT_VERSION)${RESET}"
            echo -e "${GREEN}${CHECK} Обновление не требуется${RESET}"
            ;;
        1)
            echo -e "${YELLOW}${WARN} Статус: ${BOLD}1 этап завершен${RESET}"
            echo -e "${YELLOW}${WARN} Требуется продолжить обновление (2 этап)${RESET}"
            ;;
        2)
            echo -e "${YELLOW}${WARN} Статус: ${BOLD}2 этап завершен${RESET}"
            echo -e "${YELLOW}${WARN} Требуется продолжить обновление (3 этап)${RESET}"
            ;;
        5)  
            echo -e "${GREEN}${CHECK} Система (версия $CURRENT_VERSION)${RESET}"
            echo -e "${GREEN}${CHECK} Обновление не утилитой не выполнялось${RESET}"
            ;;
        *)
            echo -e "${RED}${ERROR} Неизвестный статус: $status${RESET}"
            ;;
    esac
    echo ""
}

# ==============================================
# Шаг 1: Проверяем права root
# ==============================================

check_root() {
    echo -e "\n${BOLD}${BLUE}════════════════════════════════════════${RESET}"
    echo -e "${BOLD}${CYAN}    ПОЭТАПНОЕ ОБНОВЛЕНИЕ ASTRA LINUX${RESET}"
    echo -e "${BOLD}${BLUE}════════════════════════════════════════${RESET}\n"
    
    if [[ $EUID -ne 0 ]]; then
        echo -e "${RED}${ERROR} Ошибка: нужны права root!${RESET}"
        echo -e "${YELLOW}${INFO} Используйте: sudo $0${RESET}\n"
        exit 1
    else
        echo -e "${GREEN}${CHECK} Права root: OK${RESET}"
    fi
}

# ==============================================
# Шаг 2: Читаем версию
# ==============================================

get_current_version() {
    if [[ -f "$VERSION_FILE" ]]; then
        CURRENT_VERSION=$(cat "$VERSION_FILE" | tr -d ' \t\n\r')
        echo -e "${GREEN}${CHECK} Текущая версия: ${BOLD}${CYAN}$CURRENT_VERSION${RESET}"
    else
        echo -e "${RED}${ERROR} Файл версии не найден: $VERSION_FILE${RESET}"
        CURRENT_VERSION="unknown"
        exit 1
    fi
}

# ==============================================
# Шаг 3: Проверяем статус и версию
# ==============================================

check_status_and_version() {
    local status=$(get_status)
    
    echo ""
    
    # Если система уже обновлена до целевой версии
    if [[ "$CURRENT_VERSION" == "$TARGET_VERSION" ]]; then
        echo -e "${GREEN}${CHECK} ${BOLD}Система обновлена до версии $TARGET_VERSION${RESET}"
        
        # Если статус 0 - всё хорошо, выходим
        if [[ "$status" == "1072" ]]; then
            echo -e "${GREEN}${CHECK} Все этапы завершены${RESET}\n"
            exit 0
        fi
        
        # Если статус 1 - система обновлена, но защита не установлена
        if [[ "$status" == "1" ]]; then
            echo -e "${YELLOW}${WARN} Система обновлена, но защита не установлена${RESET}"
            echo -e "${CYAN}${ARROW} Продолжаем со 2 этапа${RESET}"
            STAGE=2
            return
        fi
        
        # Если статус 2 - защита установлена, нужна чистка
        if [[ "$status" == "2" ]]; then
            echo -e "${YELLOW}${WARN} Защита установлена, требуется чистка${RESET}"
            echo -e "${CYAN}${ARROW} Продолжаем с 3 этапа${RESET}"
            STAGE=3
            return
        fi
    fi
    
    # Если версия ниже целевой
    echo -e "${YELLOW}${WARN} Текущая версия ($CURRENT_VERSION) ниже целевой ($TARGET_VERSION)${RESET}"
    show_status_info
    
    # Определяем этап на основе статуса
    case $status in
        5)
            echo -e "${CYAN}${ARROW} Начинаем обновление с 1 этапа${RESET}"
            STAGE=1
            ;;
        1)
            echo -e "${CYAN}${ARROW} Продолжаем со 2 этапа (установка защиты)${RESET}"
            STAGE=2
            ;;
        2)
            echo -e "${CYAN}${ARROW} Продолжаем с 3 этапа (чистка и исправление)${RESET}"
            STAGE=3
            ;;
        *)
            echo -e "${RED}${ERROR} Неизвестный статус, сбрасываем на 5${RESET}"
            set_status 5
            STAGE=1
            ;;
    esac
    echo ""
}

# ==============================================
# Шаг 4: Запрос на обновление
# ==============================================

ask_update() {
    local message=""
    
    case $STAGE in
        1)
            message="Начать обновление системы до версии $TARGET_VERSION (1 этап)? После завершения потребуется перезагрузка"
            ;;
        2)
            message="Установить корпоративную систему защиты (2 этап)? После завершения потребуется перезагрузка"
            ;;
        3)
            message="Выполнить чистку системы и исправление багов (3 этап)?"
            ;;
    esac
    
    echo ""
    read -p "$(echo -e ${YELLOW}${message} [y/N]: ${RESET})" -n 1 -r
    echo ""
    
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        echo -e "\n${GREEN}${ROCKET} Запускаем этап $STAGE...${RESET}\n"
        return 0
    else
        echo -e "\n${YELLOW}${WARN} Обновление отменено пользователем${RESET}\n"
        exit 0
    fi
}

# ==============================================
# ЭТАП 1: Обновление системы до 1.7.10
# ==============================================

stage1_update_system() {
    echo -e "${BOLD}${BLUE}━━━ ЭТАП 1: Обновление системы до $TARGET_VERSION ━━━${RESET}\n"
    
    mgmt_server=$(awk -F' *= *' '/^ *server *=/{print $2}' /etc/puppetlabs/puppet/puppet.conf)
    if [[ -z "$mgmt_server" ]]; then
        echo -e "${RED}${ERROR} Не удалось получить адрес сервера управления из $puppet_conf${RESET}"
        exit 1
    fi
    echo -e "${GREEN}${CHECK} Сервер управления: ${BOLD}${CYAN}$mgmt_server${RESET}"

    echo -e "\n${BLUE}${INFO} Остановка и отключение службы Puppet...${RESET}"
    systemctl stop puppet.service 2>/dev/null 
    systemctl disable puppet.service 2>/dev/null
    sleep 5

    echo -e "\n${BLUE}${INFO} Настройка репозиториев Astra...${RESET}"
    repo_file="/etc/apt/sources.list"
    cat > "$repo_file" << EOF
# Astra Linux 1.7.10 репозитории
# Сервер управления: ${mgmt_server}
# Сгенерировано: $(date)

deb http://${mgmt_server}/astra/1.7.10/repository-base/ 1.7_x86-64 contrib main non-free
deb http://${mgmt_server}/astra/1.7.10/repository-update/ 1.7_x86-64 contrib main non-free
deb http://${mgmt_server}/astra/1.7.10/repository-extended/ 1.7_x86-64 contrib main non-free
deb [trusted=yes] http://${mgmt_server}/astra/1.7/custom/ 1.7_x86-64 contrib main non-free
EOF
    
    if [[ $? -eq 0 ]]; then
        echo -e "${GREEN}${CHECK} Репозитории настроены: $repo_file${RESET}"
    else
        echo -e "${RED}${ERROR} Ошибка настройки репозиториев${RESET}"
        exit 1
    fi

    echo -e "\n${BLUE}${INFO} Очистка старых репозиториев...${RESET}"
    
    if ls /etc/apt/sources.list.d/*.list 2>/dev/null 1>/dev/null; then
        echo -e "${YELLOW}${WARN} Найдены файлы в /etc/apt/sources.list.d/${RESET}"
        echo -e "${BLUE}${INFO} Файлы для удаления:${RESET}"
        ls -la /etc/apt/sources.list.d/*.list 2>/dev/null || echo "  (нет .list файлов)"
        rm -f /etc/apt/sources.list.d/*.list 2>/dev/null
        echo -e "${GREEN}${CHECK} Все .list файлы удалены${RESET}"
    else
        echo -e "${GREEN}${CHECK} Папка /etc/apt/sources.list.d/ пуста${RESET}"
    fi

    echo -e "\n${BLUE}${INFO} Обновление списка пакетов...${RESET}"
    apt update
    sleep 3

    echo -e "\n${BLUE}${INFO} Загрузка пакетов...${RESET}"
    apt dist-upgrade --download-only -y

    echo -e "\n${BLUE}${INFO} Подготовка системы к обновлению...${RESET}"
    dpkg -s gk-kvm >/dev/null 2>&1 && { apt update && apt install --only-upgrade gk-kvm; } || true
    dpkg -s secretnet >/dev/null 2>&1 && { sudo dpkg -P secretnet; } || true
    dpkg -s sns >/dev/null 2>&1 && { sudo dpkg -P sns; } || true
    dpkg -s gk-kvm >/dev/null 2>&1 && { tarm_unlock; } || true
    echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

    echo -e "${BLUE}${INFO} Выполняется обновление...${RESET}"
    /usr/sbin/astra-update -A -r -T -K || {
        echo -e "${RED}${ERROR} Ошибка обновления пакетов${RESET}"
        exit 1
    }

    /usr/bin/apt -o Dpkg::Options::='--force-confold' install -y gk-eosdo xrdp astra-version --reinstall
    dpkg -s gk-kvm >/dev/null 2>&1 && { /usr/bin/apt -o Dpkg::Options::='--force-confold' install -y gk-kvm --reinstall; } || true
    dpkg -s gk-kvm >/dev/null 2>&1 && { tarm_lock; } || true

    if [[ -f "$VERSION_FILE" ]]; then
        NEW_VERSION=$(cat "$VERSION_FILE" | tr -d ' \t\n\r')
        if [[ "$NEW_VERSION" == "$TARGET_VERSION" ]]; then
            echo -e "${GREEN}${CHECK} ${BOLD}Система успешно обновлена до $TARGET_VERSION${RESET}"
        else
            echo -e "${RED}${ERROR} Версия системы: $NEW_VERSION (ожидалось $TARGET_VERSION)${RESET}"
            echo -e "${RED}${ERROR} Обновление прошло с ошибкой!${RESET}"
            exit 1
        fi
    fi
    
    # Устанавливаем статус 1
    set_status 1
    
    echo -e "\n${GREEN}${CHECK} ${BOLD}1 этап завершен! Система обновлена до $TARGET_VERSION${RESET}"
    echo -e "${YELLOW}${REBOOT} Требуется перезагрузка для продолжения${RESET}"
    echo -e "${YELLOW}${INFO} После перезагрузки запустите скрипт снова ${RESET}\n"
    ask_reboot
}

# ==============================================
# ЭТАП 2: Установка корпоративной системы защиты
# ==============================================

stage2_install_security() {
    mgmt_server=$(awk -F' *= *' '/^ *server *=/{print $2}' /etc/puppetlabs/puppet/puppet.conf)
    if [[ -z "$mgmt_server" ]]; then
        echo -e "${RED}${ERROR} Не удалось получить адрес сервера управления из $puppet_conf${RESET}"
        exit 1
    fi
    echo -e "${BOLD}${BLUE}━━━ ЭТАП 2: Установка Secret Net ━━━${RESET}\n"
    
    if [[ -f "$VERSION_FILE" ]]; then
        CURRENT_VER=$(cat "$VERSION_FILE" | tr -d ' \t\n\r')
        if [[ "$CURRENT_VER" != "$TARGET_VERSION" ]]; then
            echo -e "${RED}${ERROR} Система не обновлена до $TARGET_VERSION (текущая: $CURRENT_VER)${RESET}"
            echo -e "${RED}${ERROR} Сначала выполните 1 этап обновления${RESET}"
            exit 1
        fi
    fi
    
    echo -e "${BLUE}${INFO} Установка SecretNet...${RESET}"
    cd /tmp/
    wget http://$mgmt_server/SN/secretnet_1.12-4844.astra1.7_amd64.deb
    apt install -y /tmp/secretnet_1.12-4844.astra1.7_amd64.deb
    echo -e "${BLUE}${INFO} Установка SecretNet выполнена${RESET}"

    # Устанавливаем статус 2
    set_status 2
    
    echo -e "\n${GREEN}${CHECK} ${BOLD}2 этап завершен! Secretnet установлен${RESET}"
    echo -e "${YELLOW}${REBOOT} Требуется перезагрузка для продолжения${RESET}"
    echo -e "${YELLOW}${INFO} После перезагрузки запустите скрипт снова ${RESET}\n"
    ask_reboot
}

# ==============================================
# ЭТАП 3: Чистка системы и исправление багов
# ==============================================

stage3_clean_and_fix() {
    echo -e "${BOLD}${BLUE}━━━ ЭТАП 3: Чистка системы и исправление багов ━━━${RESET}\n"
    
    echo -e "${BLUE}${INFO} Запуск puppet...${RESET}"
    /opt/puppetlabs/bin/puppet agent -t;
    /opt/puppetlabs/bin/puppet agent -t;

    echo -e "${BLUE}${INFO} Финальное обновление пакетов...${RESET}"
    /usr/sbin/astra-update -A -r -T

    echo -e "${BLUE}${INFO} Исправление печати kerberos...${RESET}"
    rm /usr/lib/cups/backend/smb
    ln -s /usr/libexec/samba/smbspool_krb5_wrapper /usr/lib/cups/backend/smb
    chmod 700 /usr/lib/cups/backend/smb

    echo -e "${BLUE}${INFO} Очистка старых ядер...${RESET}"
    base_kernel=$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")

      kernels_to_remove=$(dpkg -l 'linux-*' | sed -n '/^ii/p' | \
                         sed "/$base_kernel/d" | \
                         sed 's/^[^ ]* [^ ]* \([^ ]*\).*/\1/' | \
                         sed -n '/[0-9]/p' | \
                         head -n -1)

      if [ -n "$kernels_to_remove" ]; then
        apt purge -y $kernels_to_remove
      fi

    echo -e "${BLUE}${INFO} Очистка пакетов...${RESET}"
    apt clean
    apt autoclean
    apt autopurge -y
    aptitude purge ~c -y

    echo -e "${BLUE}${INFO} Запуск puppet и возвращение в автозапуск...${RESET}"
    systemctl enable puppet --now
    
    echo -e "${GREEN}${CHECK} Чистка и исправление завершены${RESET}\n"
    
    set_status 1072
    
    echo -e "\n${BOLD}${GREEN}════════════════════════════════════════${RESET}"
    echo -e "${BOLD}${GREEN}  ✅ ОБНОВЛЕНИЕ УСПЕШНО ЗАВЕРШЕНО!${RESET}"
    echo -e "${BOLD}${GREEN}════════════════════════════════════════${RESET}"
    echo -e "${GREEN}${CHECK} Система: ${BOLD}$TARGET_VERSION${RESET}"
    echo -e "${GREEN}${SHIELD} Защита: ${BOLD}установлена${RESET}"
    echo -e "${GREEN}${CLEAN} Чистка: ${BOLD}выполнена${RESET}"
    echo -e "${BOLD}${GREEN}════════════════════════════════════════${RESET}\n"
    
    if [[ -f /var/run/reboot-required ]]; then
        echo -e "${YELLOW}${WARN} Рекомендуется перезагрузить систему${RESET}"
        ask_reboot
    fi
}

# ==============================================
# Запрос перезагрузки
# ==============================================

ask_reboot() {
    read -p "$(echo -e ${YELLOW}Перезагрузить сейчас? [y/N]: ${RESET})" -n 1 -r
    echo ""
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        echo -e "${BLUE}${INFO} Перезагрузка...${RESET}"
        reboot
    else
        echo -e "${YELLOW}${WARN} Перезагрузка отложена${RESET}"
        echo -e "${YELLOW}${WARN} Не забудьте перезагрузить систему вручную!${RESET}"
        echo -e "${YELLOW}${INFO} Для продолжения обновления запустите: sudo $0${RESET}"
    fi
}

# ==============================================
# MAIN
# ==============================================

main() {
    check_root
    init_marker
    get_current_version
    check_status_and_version
    ask_update
    
    case $STAGE in
        1) stage1_update_system ;;
        2) stage2_install_security ;;
        3) stage3_clean_and_fix ;;
        *)
            echo -e "${RED}${ERROR} Неизвестный этап: $STAGE${RESET}"
            exit 1
            ;;
    esac
}

main "$@"