#!/bin/bash
#глобальные переменные
ssh_password=""
sshpass_path="/tmp/autoinstall/sshpass"
printer_ip=""
printer_info=""
printer_hostname=""
ppd_dir="/mnt/cifs/distr1/Astra Linux/Принтеры/Драйверы/test/ppd/Kyocera"
ssh_root="$sshpass_path -p "$ssh_password" ssh -n administrator@localhost"

#подготовка временной директории
prepare_temp_dir() {
    local temp_dir="/tmp/autoinstall"

    # Создание временной директории
    if ! mkdir -p "$temp_dir"; then
        echo "Ошибка: не удалось создать временную директорию $temp_dir" >&2
        return 1
    fi

    # Проверка доступа к сетевой папке
    if ! ls /mnt/cifs/distr1 >/dev/null 2>&1; then
        echo "Ошибка: не удалось получить доступ к /mnt/cifs/distr1" >&2
        return 1
    fi

    echo "Временная директория $temp_dir успешно подготовлена"
    return 0
}

#копирование основного инструмента доступа
cp_sshpass() {
    local sshpass_src="/mnt/cifs/distr1/Astra Linux/Принтеры/Драйверы/test/sshpass/1.7/sshpass"
    local sshpass_dest="/tmp/autoinstall/sshpass"

    # Проверка существования исходного файла
    if [ ! -f "$sshpass_src" ]; then
        echo "Ошибка: исходный файл sshpass не найден по пути $sshpass_src"
        return 1
    fi

    # Проверка существования целевой директории
    if [ ! -d "/tmp/autoinstall" ]; then
        mkdir -p "/tmp/autoinstall" || {
            echo "Ошибка: не удалось создать директорию /tmp/autoinstall"
            return 1
        }
    fi

    # Копирование файла
    cp "$sshpass_src" "$sshpass_dest" || {
        echo "Ошибка: не удалось скопировать sshpass в $sshpass_dest"
        return 1
    }

    echo "Файл sshpass успешно скопирован"
    return 0
}


#Запрос пароля рут
ask_root() {
    local attempts=3
    while (( attempts-- > 0 )); do
        read -sp "Введите пароль SSH для root: " ssh_password
        echo ""

        # Проверяем пароль, пытаясь выполнить простую команду
        if $sshpass_path -p "$ssh_password" ssh -n -o StrictHostKeyChecking=no administrator@localhost "exit" 2>/dev/null; then
            # Если пароль верный, выполняем подключение
            $sshpass_path -p "$ssh_password" ssh -n administrator@localhost
            return 0
        else
            echo "Неверный пароль. Осталось попыток: $attempts"
        fi
    done

    echo "Ошибка: исчерпаны все попытки ввода пароля."
    return 1
}

#запрос ip принтера
ask_ip() {
    read -p "Введите IP-адрес принтера: " printer_ip
    return 0
}


avahi_utils() {
    # Проверяем, установлен ли avahi-utils, и устанавливаем если нет
    if $sshpass_path -p "$ssh_password" ssh administrator@localhost "dpkg -s avahi-utils &>/dev/null"; then
        echo "avahi-utils уже установлен, пропускаем установку."
        return 0
    else
        echo "Установка avahi-utils..."
        $sshpass_path -p "$ssh_password" ssh administrator@localhost "sudo apt-get install -y avahi-utils"
        return 0
    fi
}

#горжусь этой функцией, убирает лютые городушки
get_printer_info() {
    printer_info=$(
        $sshpass_path -p "$ssh_password" ssh -n administrator@localhost \
        'avahi-browse -rtp _ipp._tcp 2>/dev/null | \
        grep -F "'"$printer_ip"'" | \
        grep -v "IPv6" | \
        grep -oP "\"ty=\\K[^\"]*"'
    )
    return 0
}

get_printer_hostname() {
    local attempts=0
    local max_attempts=3
    printer_hostname=""

    while [[ $attempts -lt $max_attempts ]]; do
        printer_hostname=$($sshpass_path -p "$ssh_password" ssh -n administrator@localhost "avahi-resolve -a $printer_ip | cut -f2" 2>/dev/null)

        if [[ -n "$printer_hostname" ]]; then

            seek_name
            break # Выход из цикла при успешном получении имени
        fi

        attempts=$((attempts + 1))
        if [[ $attempts -lt $max_attempts ]]; then
            sleep 1
        fi
    done

    if [[ -z "$printer_hostname" ]]; then
        printer_hostname="$printer_ip"
        echo "Не удалось найти принтер в сети, придется указать модель вручную" >&2
        indicate_model
    fi
}

#определение и установка
seek_name() {
    if [[ -n "$hostname" && -z "$printer_info" ]]; then
        indicate_model
        return 0
    elif [[ "$printer_info" == *"Pantum"* ]]; then
        echo "printer is $printer_info"
        pantum_install_drv
        pantum_install_printer
        return 0
    elif [[ "$printer_info" == *"Kyocera"* ]]; then
        echo "printer is $printer_info"
        kyocera_install1
        return 0
    elif [[ "$printer_info" == *"HP"* ]]; then
        echo "printer is $printer_info"
        hp_install
        return 0
    fi
}

indicate_model() {
    echo "Выбери модель устройства:"
    echo "1) Kyocera"
    echo "2) Pantum"
    echo "3) HP"
    echo "4) Другая"

    read -p "Введите номер выбранной модели: " model_choice

    case $model_choice in
        1)
            printer_model="Kyocera"
            echo "Выбрана модель: $printer_model"

            if declare -f kyocera_install1 > /dev/null; then
                choose_ppd
                return 0

            else
                echo "Ошибка: функция kyocera_install не найдена"
                return 1
            fi
            ;;
        2)
            printer_model="Pantum"
            echo "Выбрана модель: $printer_model"
            if declare -f pantum_install_drv > /dev/null; then
                choose_ppd
                return 0

            else
                echo "Ошибка: функция pantum_install не найдена"
                return 1
            fi
            ;;
        3)
            printer_model="HP"
            echo "Выбрана модель: $printer_model"
            if declare -f hp_install > /dev/null; then
                manual_hp_install
                return 0

            else
                echo "Ошибка: функция hp_install не найдена"
                return 1
            fi
            ;;
        4)
            read -p "Введите название модели: " printer_model
            echo "Выбрана модель: $printer_model"
            ;;
        *)
            echo "Некорректный выбор, попробуйте снова"
            indicate_model
            return 1
            ;;
    esac
}

choose_ppd() {
    local target_dir
    local basename_noext
    local newname

    # Выбираем каталог в зависимости от модели принтера
    case "$printer_model" in
        "Kyocera")
            target_dir="/mnt/cifs/distr1/Astra Linux/Принтеры/Драйверы/test/ppd/Kyocera"
            basename_prefix="Kyocera_"
            completion_func="kyocera_install2"
            ;;
        "Pantum")
            target_dir="/usr/share/cups/model/Pantum"
            basename_prefix="Pantum_"
            completion_func="pantum_install_drv"
            ;;
        *)
            echo "Ошибка: неизвестная модель принтера"
            return 1
            ;;
    esac

    # Проверяем существование каталога
    if [ ! -d "$target_dir" ]; then
        echo "Ошибка: каталог $target_dir не существует!"
        return 1
    fi

    # Переходим в целевой каталог и получаем список PPD файлов
    cd "$target_dir" || return 1
    files=(*.ppd)

    # Проверяем, есть ли PPD файлы
    if [ ${#files[@]} -eq 0 ]; then
        echo "Нет PPD файлов в каталоге $target_dir"
        return 1
    fi

    # Выводим список файлов с номерами
    echo "Доступные PPD файлы:"
    for i in "${!files[@]}"; do
        printf "%d) %s\n" "$((i+1))" "${files[i]}"
    done

    # Запрашиваем выбор пользователя
    while true; do
        printf "Введите номер PPD файла (1-%d): " "${#files[@]}"
        read choice

        # Проверяем ввод
        if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "${#files[@]}" ]; then
            selected_file="${files[$((choice-1))]}"
            selected_path="$target_dir/$selected_file"
            echo "Выбран файл: $selected_path"

            # Формируем новое имя (без расширения .ppd)
            basename_noext="$(basename "$selected_file" .ppd)"
            newname="${basename_prefix}${basename_noext}"
            printer_info="$newname"
            echo "Новое имя: $printer_info"

            # Вызываем соответствующую завершающую функцию
            if declare -f "$completion_func" > /dev/null; then
                "$completion_func"
                return 0
            else
                echo "Ошибка: функция $completion_func не найдена"
                return 1
            fi
        else
            echo "Неверный выбор. Пожалуйста, введите число от 1 до ${#files[@]}."
        fi
    done
}

pantum_install_drv() {
    echo "Обнаружен принтер Pantum. Начинаю установку драйверов..."

            # Копируем драйверы во временную директорию
        cp -r "/mnt/cifs/distr1/Astra Linux/Принтеры/Драйверы/Pantum/M7100DW" /tmp/

        echo "Установка драйверов Pantum и avahi-utils..."

        # Выполняем установку через SSH
        $sshpass_path -p "$ssh_password" ssh -o StrictHostKeyChecking=no -X administrator@localhost "
            sudo -i << 'EOF'
            cp /home/administrator/.Xauthority ~/
            apt-get install -y libjpeg8 || apt-get install -f -y
            cd /tmp/M7100DW
            chmod +x install.sh
            ./install.sh
EOF"
        echo "Установка драйверов Pantum завершена."
        pantum_install_printer

}

pantum_install_printer() {
    # Нормализуем имя принтера для пути PPD
    local base_name=$(echo "$printer_info" | sed 's/^Pantum_//; s/ Series PS$//; s/ Series$//; s/ PS$//')
    local original_name=$(echo "$printer_info" | sed 's/^Pantum_//')
    
    # Создаем массив всех возможных вариантов имен PPD-файлов
    local ppd_variants=(
        # Оригинальное имя как есть
        "/usr/share/cups/model/Pantum/${original_name}"
        
        # Варианты с разными комбинациями Series и PS
        "/usr/share/cups/model/Pantum/${base_name} Series PS.ppd"
        "/usr/share/cups/model/Pantum/${base_name} Series.ppd"
        "/usr/share/cups/model/Pantum/${base_name} PS.ppd"
        "/usr/share/cups/model/Pantum/${base_name}.ppd"
        
        # Варианты с дефисами вместо пробелов
        "/usr/share/cups/model/Pantum/$(echo "$base_name" | tr ' ' '-')-Series.ppd"
        "/usr/share/cups/model/Pantum/$(echo "$base_name" | tr ' ' '-').ppd"
        
        # Варианты с разным порядком слов
        "/usr/share/cups/model/Pantum/$(echo "$base_name" | sed 's/\(.*\) \(.*\)/\2 \1/') Series.ppd"
    )

    # Добавляем варианты для имен с цифрами и без (например, P2500 и P2500N)
    if [[ "$base_name" =~ [0-9][A-Za-z]$ ]]; then
        local base_without_last_char="${base_name%?}"
        ppd_variants+=(
            "/usr/share/cups/model/Pantum/${base_without_last_char} Series.ppd"
            "/usr/share/cups/model/Pantum/${base_without_last_char}.ppd"
        )
    fi

    # Пробуем каждый вариант PPD-файла
    local found_ppd=""
    for ppd in "${ppd_variants[@]}"; do
        echo "Проверяем PPD: $ppd"
        if $sshpass_path -p "$ssh_password" ssh -n administrator@localhost "sudo test -f \"$ppd\""; then
            found_ppd="$ppd"
            echo "Найден PPD-файл: $found_ppd"
            break
        fi
    done

    if [[ -z "$found_ppd" ]]; then
        # Попробуем найти файл без учета регистра (если файловая система чувствительна к регистру)
        echo "Пытаемся найти PPD без учета точного совпадения регистра..."
        possible_ppd=$($sshpass_path -p "$ssh_password" ssh -n administrator@localhost \
            "sudo find /usr/share/cups/model/Pantum/ -iname \"*${base_name}*.ppd\" -print -quit" | head -1)
        
        if [[ -n "$possible_ppd" ]]; then
            found_ppd="$possible_ppd"
            echo "Найден похожий PPD-файл: $found_ppd"
        else
            echo "Ошибка: Не найден PPD-файл для принтера $printer_info"
            echo "Проверенные пути:"
            printf "  - %s\n" "${ppd_variants[@]}"
            return 1
        fi
    fi

    echo "Используется PPD-файл: $found_ppd"

    # Пытаемся добавить принтер
    printer_add_output=$($sshpass_path -p "$ssh_password" ssh -n administrator@localhost \
        'sudo lpadmin -p '"$printer_hostname"' -v "https://'"$printer_hostname"'" -P "'"$found_ppd"'" -E -o printer-is-shared=false' 2>&1)

    # Проверяем результат
    if [[ $? -eq 0 ]]; then
        echo "Принтер $printer_hostname успешно добавлен"
        return 0
    else
        echo "Ошибка добавления принтера $printer_hostname"
        echo "Детали: $printer_add_output"

        # Дополнительная проверка для устаревших драйверов
        if [[ "$printer_add_output" == *"устаревшими"* ]]; then
            echo "Предупреждение: Используются устаревшие драйверы принтера"
        fi

        return 1
    fi
}

disable_shared_printers() {
    echo "Отключаем параметр Shared у всех принтеров через SSH"
    # Получаем список всех принтеров через ssh
    printers=$($sshpass_path -p "$ssh_password" ssh -n administrator@localhost "lpstat -p | awk '{print \$2}'")
    for printer in $printers; do
        echo "Отключаем Shared у принтера: $printer"
        $sshpass_path -p "$ssh_password" ssh -n administrator@localhost "sudo lpadmin -p \"$printer\" -o printer-is-shared=false"
    done
    # Перезапускаем CUPS через ssh
    #sleep 10
    #$sshpass_path -p "$ssh_password" ssh -n administrator@localhost "sudo systemctl restart cups"
    #echo "Параметр Shared отключен у всех принтеров"

}

manual_hp_install(){
    printer_hostname="$printer_ip"
    hp_install
}
hp_install_usb(){
    $sshpass_path -p "$ssh_password" ssh -n administrator@localhost "hp-setup -i -a <<< 0"


}

hp_install() {
    echo "Начало установки HP"

    $sshpass_path -p "$ssh_password" ssh -n administrator@localhost "sudo apt-get install -y expect"

    cat > /tmp/autoinstall/hp-plugin.expect << 'EOS'
#!/usr/bin/expect -f
set timeout 60
spawn hp-plugin -i

expect {
    "warning: It is not recommended to run 'hp-plugin' in a root mode." {
        exp_continue
    }
    "The driver plugin for HPLIP.*already to be installed" {
        exp_continue
    }
    "Do you wish to download and re-install the plug-in? (y=yes*, n=no, q=quit) ?" {
        send "y\r"
        exp_continue
    }
    "Enter option (p=from package*, d=download, q=quit) ?" {
        send "p\r"
        exp_continue
    }
    "Do you accept the license terms for the plug-in (y=yes*, n=no, q=quit) ?" {
        send "y\r"
        exp_continue
    }
    "Done." {
        exit 0
    }
    timeout {
        send_user "\nTimeout occurred during plugin installation\n"
        exit 1
    }
    eof
}
EOS

    $sshpass_path -p "$ssh_password" ssh -n administrator@localhost "sudo chmod +x /tmp/autoinstall/hp-plugin.expect"
    $sshpass_path -p "$ssh_password" ssh -n administrator@localhost "sudo /tmp/autoinstall/hp-plugin.expect"

    echo "Установка HP Plugin завершена"

    # Установка принтера
    $sshpass_path -p "$ssh_password" ssh -n administrator@localhost "sudo hp-setup -x -i -a $printer_hostname"

    echo "Установка и настройка принтера и факса завершены"
    $sshpass_path -p "$ssh_password" ssh -n administrator@localhost "lpstat -v | grep -i 'fax' | awk '{print \$3}' | cut -d: -f1 | xargs -I{} sudo lpadmin -x {}"
    disable_shared_printers
}



kyocera_install1(){
    echo "начало автоустановки Kyocera"

    # Проверяем, существует ли директория с PPD-файлами
    if [ ! -d "$ppd_dir" ]; then
        echo "Ошибка: директория с PPD-файлами не найдена: $ppd_dir"
        return 1
    fi

    # Проверяем, есть ли информация о принтере
    if [ -z "$printer_info" ]; then
        echo "Ошибка: информация о принтере не указана"
        return 1
    fi

    # Заменяем пробелы в имени принтера на подчеркивания
    clean_printer_name=$(echo "$printer_info" | tr ' ' '_')
    echo "Очищенное имя принтера: $clean_printer_name"

    echo "Поиск PPD-файла для принтера в директории: $ppd_dir"

    # Ищем подходящий PPD-файл
    found_ppd=""
    for ppd_file in "$ppd_dir"/*; do
        # Извлекаем имя файла без пути
        filename=$(basename "$ppd_file")

        # Проверяем, содержится ли информация о принтере в имени файла
        if [[ "$filename" == *"$printer_info"* ]]; then
            found_ppd="$ppd_file"
            kyocera_install3
        fi

        # Дополнительная проверка содержимого файла (если нужно)
        if grep -q -i "$printer_info" "$ppd_file"; then
            found_ppd="$ppd_file"
            kyocera_install3
        fi
    done

    # Если файл не найден - выходим
    if [ -z "$found_ppd" ]; then
        echo "Ошибка: Подходящий PPD-файл не найден"
        return 1
    fi

}

kyocera_install2() {
    echo "начало ручной установки Kyocera"
    found_ppd="$selected_path"
    clean_printer_name="$newname"
    kyocera_install3
    return 0
}


kyocera_install3() {
    select_ppd_kyo="$found_ppd"
    # Копируем PPD-файл во временную директорию с простым именем
    "$sshpass_path" -p "$ssh_password" ssh -n administrator@localhost "sudo chmod -R 777 /tmp/autoinstall"
    # Создаем упрощенное имя файла без пробелов и специальных символов
    simple_ppd_name="kyocera_printer.ppd"
    cp "$select_ppd_kyo" "/tmp/autoinstall/$simple_ppd_name"
    # Безусловно выполняем команду lpadmin с очищенным именем принтера
    echo "Добавляем принтер в систему:"
    "$sshpass_path" -p "$ssh_password" ssh -n administrator@localhost "sudo lpadmin -p \"$clean_printer_name\" -v socket://\"$printer_hostname\" -P \"/tmp/autoinstall/$simple_ppd_name\" -E -o printer-is-shared=false"

}

# Основной поток выполнения
auto_install(){
    prepare_temp_dir
    cp_sshpass
    ask_root
    ask_ip
    get_printer_info
    get_printer_hostname

}

manual_install(){
    prepare_temp_dir
    cp_sshpass
    ask_root
    ask_ip
    indicate_model
}
ui_install(){
    prepare_temp_dir
    avahi_utils
    cp_sshpass
    get_printer_info
    get_printer_hostname
}
# Главное меню выбора
start_sh(){
    echo "Выберите тип установки:"
    echo "1) Автоматическая установка"
    echo "2) Ручная установка"
    echo -n "Введите номер выбора (1 или 2): "

    read choice

    case $choice in
        1)
            echo "Выбрана автоматическая установка"
            auto_install
            ;;
        2)
            echo "Выбрана ручная установка"
            manual_install
            ;;
        *)
            echo "Некорректный выбор. Пожалуйста, запустите скрипт снова и выберите 1 или 2."

            ;;
    esac
}


# Обработка параметров
ip=""
other_params=""
noi_param=false

while [ "$#" -gt 0 ]; do
    case "$1" in
        -noi)
            noi_param=true
            shift
            ;;
        -noui)
            # Этот параметр обрабатывается в основном условии
            shift
            ;;
        -ip)
            if [ -n "$2" ]; then
                ip="$2"
                shift 2
            else
                echo "Ошибка: параметр -ip требует значения"
                exit 1
            fi
            ;;
        -p)
            if [ -n "$2" ]; then
                p="$2"
                shift 2
            else
                echo "Ошибка: параметр -p требует значения"
                exit 1
            fi
            ;;
    esac
done

# Проверка условий и вызов соответствующей функции
if [ "$noi_param" = true ]; then
    echo "можно продолжать делать грязь"
    printer_ip="$ip"
    ssh_password="$p"
    ui_install

else
    start_sh
fi
