#!/bin/bash

# Скрипт помогает установить пакеты SoftWLC плейбуками Ansible
# Предварительно устанавливает необходимые пакеты на хост, включая докер для запуска Ansible
# После происходит первоналаьная настройка, с указанием IP-адреса хоста, на который будет установлен SoftWLC (включая саму машину с Ansible) и данных для входа по SSH для Ansible.
# Затем уже Ansible последовательно устанавливает и настраивает все нужные пакеты комплекса на указанном в предыдущем шаге хосте (включая установку Docker в случае отсутствия):
#
# eltex-oui-list           : Содержит список соответствий MAC-адресов и производителей оборудования
# eltex-ems-db             : Разворачивает схему в БД MySQL для EMS
# eltex-radius-db          : Разворачивает схему в БД MySQL для RADIUS-сервера
# eltex-auth-service-db    : Разворачивает схему в БД MySQL для сервиса авторизации
# eltex-ems                : Серверная и клиентская часть СУ EMS
# eltex-radius             : RADIUS-сервер
# eltex-radius-nbi         : Северный мост (northbound) для стыка SoftWLC с вышестоящими OSS/BSS
# eltex-ngw                : Сервис, предоставляющий возможность отправки уведомлений (СМС, звонков), используемый другими пакетами комплекса
# eltex-apb                : Сервис для взаимодействия точек доступа
# eltex-pcrf               : Служба управления политиками доступа (используется BRAS)
# eltex-mercury            : Сервис по управлению Hotspot пользователями
# eltex-portal             : Портал для авторизации клиентов WiFi в схеме 'Hotspot'
# eltex-portal-constructor : Web-приложение для создания и редактирования порталов для авторизации
# eltex-wifi-cab           : Личный кабинет оператора услуги Wi-Fi
# eltex-doors              : Обеспечивает авторизацию пользователя/сервиса внутри ядра (внутреннее взаимод.)
# eltex-bruce              : Сервис-планировщик задач, обеспечивает запуск задач по установленному расписанию
# eltex-jobs               : Сервис-исполнитель задач, выполняет задачи, запущенные eltex-bruce
# eltex-disconnect-service * : Сервис обеспечивает немедленное прерывание сессии пользователя
# eltex-johnny *             : REST API к Mercury для управления Enterprise и Hotspot пользователями
# eltex-logging-service *    : Микросервис журналирования операций
# eltex-airtune *            : Сервис обеспечивает RRM (Radio Resource Management) и Client Load Balancing
#
# * - устанавливаются по умолчанию, но могут быть исключены из установки флагом MIN.

# Версия: SoftWLC 1.36, EMS 3.40
# Целевая ОС: Ubuntu (jammy 22.04, focal 20.04), AstraLinux (1.7.3, 1.7.4, 1.7.5), RedOS (7.3.1 7.3.4 7.3.5)
# Автор: Столетний СО
# ООО Предприятие Элтекс
# Новосибирск, 2025

# Модификаторы запуска скрипта:
# --install-docker			install Docker to localhost
# --start-ansible			run Ansible container
# --migrate-from-debs			migrate configs from debs to docker
# --migrate-db-backup			migrate databse from debs to docker (take backup)
# --migrate-db-restore			migrate databse from debs to docker (restore backup)
# --ansible-install-docker		install Docker to remote host
# --ansible-install-softwlc		install SoftWLC to remote host
# --test-ports				check if the application ports are open
# --backup				backup all files of SoftWLC to archive
# --restore				extract backup archive
# --run					run containers
# --stop				stop containers
# --delete				delete containers
# --recreate-service <SERVICE>		recreates specified service
# --generate-keys			generate new keys for services and restart them
# --download, -d			download, export and extract application archive with project
# --update-ems-licence			update ems/airtune licence
# --update-wifi-cab-licence		update wifi-cab licence and incremental licenсe
# --change-password			change service users passwords in configuration files
# --reconfigure				reconfiguring softwlc services using new ips
# --configure-radius-proxy             	setup radius proxy configuration
# --help, -h				help
#
# Запросы при установке укажите согласно требованиям, либо по необходимости


red=$(tput setaf 1)
green=$(tput setaf 2)
reset=$(tput sgr 0)

current_dir=$(pwd)
backup_dir="$current_dir/backup"

SOFTWLC_VERSION="1.36"
EMS_VERSION="3.40"
AIRTUNE_VERSION="1.7.1"

# Директория текущей версии softwlc ansible
CURR_FILE_VERSION_NAME="softwlc-ansible-${SOFTWLC_VERSION}"
# Путь до директории с наcтройками пользователя (my_softwlc)
INVENTORY_PATH="${current_dir}/${CURR_FILE_VERSION_NAME}/inventory"


# Public docker image registry
ELTEX_PUBLIC_REGISTRY="hub.eltex-co.ru/softwlc"
# Private docker image registry
ELTEX_PRIVATE_REGISTRY_RELEASE="secret"


# Public apt repository (need for download ansible playbook archive)
ELTEX_PUBLIC_REPO="https://archive.eltex-co.ru/wireless"
# Private apt repository (need for download ansible playbook archive)
ELTEX_PRIVATE_REPO="secret"


# Переменная, которая является рабочей. Внутри скрипта работа идёт с ней в зависимости от параметров вызова скрипта
ELTEX_REPO=${ELTEX_PUBLIC_REPO}
# Переменная, которая является рабочей. Внутри скрипта работа идёт с ней в зависимости от параметров вызова скрипта
ELTEX_DOCKER_REGISTRY=${ELTEX_PUBLIC_REGISTRY}


help="
Options:
--install-docker			install Docker to localhost
--start-ansible				run Ansible container
--migrate-from-debs			migrate configs from debs to docker
--migrate-db-backup			migrate databse from debs to docker (take backup)
--migrate-db-restore			migrate databse from debs to docker (restore backup)
--ansible-install-docker		install Docker to remote host
--ansible-install-softwlc		install SoftWLC to remote host
--test-ports				check if the application ports are open
--backup				backup all files of SoftWLC to archive
--restore				extract backup archive
--run					run containers
--stop					stop containers
--delete				delete containers
--recreate-service <SERVICE>		recreates specified service
--generate-keys				generate new keys for services and restart them
--download, -d				download, export and extract application archive with project
--update-ems-licence			update ems/airtune licence
--update-wifi-cab-licence		update wifi-cab licence and incremental licenсe
--change-password			change service users passwords in configuration files
--reconfigure				reconfiguring softwlc services using new ips
--configure-radius-proxy             	setup radius proxy configuration
--help, -h				help

"

# ------------------------------- Check and install required packages ---------------------------------------

function require_package() {
    pkgs=("$@")
    if [[ ${DISTR_ID} == "RED SOFT" ]]; then
        sudo dnf check-update
        for pkg in "${pkgs[@]}"; do
            if ! rpm -q $pkg; then
                echo -e "${green}Installing ${pkg}...${reset}"
                sudo dnf install -y $pkg
            else
                echo -e "${green}${pkg} is already installed${reset}"
            fi
        done
    else
        sudo apt update
        for pkg in "${pkgs[@]}"; do
            if ! dpkg -s "$pkg" | grep "install ok installed"; then
                echo -e "${green}Installing ${pkg}...${reset}"
                sudo apt install -y $pkg
            else
                echo "${green}${pkg} is already installed${reset}"
            fi
        done
    fi
}

# ----------------------------------------- Check Docker on host --------------------------------------------

function check_docker() {
    if ! command -v docker &>/dev/null || ! command -v docker compose &>/dev/null; then
        echo -e "${red}docker/docker-compose is not installed${reset}"
        need_install_docker_host=true
        return
    fi

    REQUIRED_COMPOSE_VERSION="2.23.3" # last for redos - 2.23.3, ubuntu - 2.33.1, astra - 2.23.3
    INSTALLED_COMPOSE_VERSION=$(docker compose version | awk '{print $4}' | tr -d ',abcdefghijklmnopqrstuvwxyz')
    if ! [[ "$(printf '%s\n' "$REQUIRED_COMPOSE_VERSION" "$INSTALLED_COMPOSE_VERSION" | sort -V | head -n1)" == "$REQUIRED_COMPOSE_VERSION" ]]; then
        echo -e "${red}docker-compose version ${INSTALLED_COMPOSE_VERSION} does not match required version ${REQUIRED_COMPOSE_VERSION}${reset}"
        need_install_docker_host=true
        return
    fi
}

# -------------------------------------- Install Docker on host by OS ---------------------------------------

function install_docker_ubuntu() {
    echo -e "${green}Install docker for Ubuntu${reset}"
    echo "Remove unofficial docker versions..."
    # Нужно просто проверить, что их нет и удалить, необходимы поставит официальный скрипт докера
    for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove -y $pkg; done

    echo -e "\nInstallation requires packages"
    require_package curl

    DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
    rm -f $DOCKER_CONFIG/cli-plugins/docker-compose
    echo -e "\nInstall official docker and docker compose..."
    curl -fsSL https://get.docker.com -o /tmp/get-docker.sh
    sh /tmp/get-docker.sh
    systemctl enable docker
    systemctl restart docker
    echo -e "${green}\nInstall is complete${reset}"
}

function install_docker_redos() {
    echo -e "${green}Install docker for REDOS${reset}"
    echo "Remove unofficial docker-compose versions..."
    dnf remove docker-compose-* -y

    echo -e "\nInstallation requires packages"
    require_package docker-ce curl

    echo -e "\nInstall official docker and docker compose..."
    export DOCKER_CONFIG=${DOCKER_CONFIG:-/usr/local/lib/docker}
    mkdir -p "${DOCKER_CONFIG}/cli-plugins"
    curl -SL https://github.com/docker/compose/releases/download/v2.23.3/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
    chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
    systemctl enable docker
    systemctl restart docker
    echo -e "${green}\nInstall is complete${reset}"
}

function install_docker_astralinux() {
    echo -e "${green}Install docker for Astra Linux${reset}"
    echo "Remove unofficial docker-compose versions..."
    apt remove docker-compose-* -y

    echo "Configure Astrlinux deb repositories"
    repos=(
    "deb https://download.astralinux.ru/astra/stable/1.7_x86-64/repository-main/ 1.7_x86-64 main contrib non-free"
    "deb https://download.astralinux.ru/astra/stable/1.7_x86-64/repository-update/ 1.7_x86-64 main contrib non-free"
    "deb https://download.astralinux.ru/astra/stable/1.7_x86-64/repository-base/ 1.7_x86-64 main contrib non-free"
    "deb https://download.astralinux.ru/astra/stable/1.7_x86-64/repository-extended/ 1.7_x86-64 main contrib non-free"
    )

    if [ -f /etc/apt/sources.list.d/ansible.list ]; then
        for repo_index in "${!repos[@]}"; do
            if grep -Fxq "${repos[$repo_index]}" /etc/apt/sources.list.d/ansible.list; then
                unset repos["$repo_index"]
            fi
        done
    fi

    if [ ${#repos[@]} -ne 0 ]; then
        for repo in "${repos[@]}"; do
            echo "$repo" >>/etc/apt/sources.list.d/ansible.list
        done
        echo "SourceList was updated"
    fi

    require_package docker.io curl

    echo -e "\nInstall official docker compose..."
    export DOCKER_CONFIG=${DOCKER_CONFIG:-/usr/local/lib/docker}
    mkdir -p "${DOCKER_CONFIG}/cli-plugins"
    curl -SL https://github.com/docker/compose/releases/download/v2.23.3/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
    chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
    chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
    systemctl enable docker
    systemctl restart docker
    echo -e "${green}\nInstall is complete${reset}"
}

# ----------------------------------------- Install Docker on host ------------------------------------------

function install_docker() {
    if ! ${need_install_docker_host}; then
        return
    fi
    DISTR_ID=$(lsb_release -i --short)

    case ${DISTR_ID} in
    "RED SOFT") install_docker_redos ;;
    "AstraLinux") install_docker_astralinux ;;
    "Ubuntu") install_docker_ubuntu ;;
    esac
}

# --------------------------------------- Download Ansible archive ------------------------------------------

function download_softwlc_ansible(){
    if ! ${need_download_ansible} && ! ${need_default_install}; then
        return
    fi
    if [ ! -f "softwlc-ansible-${SOFTWLC_VERSION}.tar.gz" -a ! -f "softwlc-ansible-latest.tar.gz" ]; then
    	echo -e "${green}Downloading SoftWLC Ansible playbook${reset}"
    	require_package wget
    	wget $ELTEX_REPO/help/softwlc-$SOFTWLC_VERSION/softwlc-ansible-$SOFTWLC_VERSION.tar.gz
    	if [ $? -ne 0 ]; then
    	    echo -e "${red}Error while trying to load playbooks. Check the site availability or your internet connection.${reset}"
    	    exit 1
        fi
    fi
    # Если скачан архив softwlc-ansible-latest.tar.gz - переключаемся на работу с ним, если нет - оставляем версионный (по дефолту качается версионный, зависит от переменной SOFTWLC_VERSION)
    #if [ -f "softwlc-ansible-latest.tar.gz" ]; then
    #    CURR_FILE_VERSION_NAME="softwlc-ansible-latest"
    #fi
    echo -e "\n${green}Extract SoftWLC installer...${reset}"
    if [ ! -d $current_dir/$CURR_FILE_VERSION_NAME/ ]; then
        tar -xzf $CURR_FILE_VERSION_NAME.tar.gz
        mv $current_dir/$CURR_FILE_VERSION_NAME/docker-compose.yml $current_dir/docker-compose.yml
    else
        backup_softwlc_ansible_files
        echo -n "You already have a softwlc-ansible configuration directory. Do you want to replace this configuration with default parameters from the archive? [y/N] (default=\"N\"): "
        read ans
        if [[ "$ans" =~ ^(y|Y|д|Д)$ ]]; then
            tar -xzf $CURR_FILE_VERSION_NAME.tar.gz
            mv $current_dir/$CURR_FILE_VERSION_NAME/docker-compose.yml $current_dir/docker-compose.yml
        else
            echo "${red}Extract aborted!${reset}"
        fi
    fi

    # Копирование inventory/sample => inventory/my_softwlc
    if [ ! -d $INVENTORY_PATH/my_softwlc ]; then
        cp -rfp $INVENTORY_PATH/sample $INVENTORY_PATH/my_softwlc
    else
        echo -n "You already have my_softwlc configurations. Do you want to replace this configuration with default parameters from inventory/sample ? [y/N] (default=\"N\"): "
        read ans
        if [[ "$ans" =~ ^(y|Y|д|Д)$ ]]; then
            cp -rfp $INVENTORY_PATH/sample $INVENTORY_PATH/my_softwlc
        else
            if [ ! -f $INVENTORY_PATH/my_softwlc/inventory.yml ]; then
                cp -fp $INVENTORY_PATH/sample/inventory.yml $INVENTORY_PATH/my_softwlc/inventory.yml
            fi
            if [ ! -f $INVENTORY_PATH/my_softwlc/group_vars/all.yml ]; then
                cp -fp $INVENTORY_PATH/sample/group_vars/all.yml $INVENTORY_PATH/my_softwlc/group_vars/all.yml
            fi
        fi
    fi
    # Изменение пути к файлу inventory в конфиге ansible
    sed -i "s|^inventory =.*|inventory = inventory\/my_softwlc\/inventory.yml|" $current_dir/$CURR_FILE_VERSION_NAME/ansible.cfg
}

# --------------------------------------- Backup host config files -------------------------------------------

function backup_softwlc_ansible_files() {
    echo -n "Do you want to backup your configuration files ? [Y/n] (default=\"Y\"): "
    read ans
    if [[ "$ans" =~ ^(n|N|н|Н)$ ]]; then
        return
    fi
    mkdir -p "${backup_dir}"
    tar -C $current_dir -czf $backup_dir/backup_$(date +"%Y%m%dT%H%M%S").tar.gz $CURR_FILE_VERSION_NAME/*
    echo "${green}Backup has been completed!${reset}"
}

# ------------------------------------- Preparing the inventory file -----------------------------------------

# Валидация IP адреса через regex
function valid_ipv4() {
    local ip=$1
    local stat=1
    # Проверка пустого значения
    if [[ -z $ip ]]; then
        echo -e "${red}IP address cannot be empty${reset}"
        exit 1
    fi
    # Проверка, что это не localhost (так как этот адрес приведёт пользователя браузера на собственный ПК)
    if [[ $ip == "127.0.0.1" || $ip == "::1" ]]; then
        echo -e "${red}Cannot assign localhost IP '$1' to server IP address${reset}"
        exit 1
    fi

    if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
        OIFS=$IFS
        IFS='.'
        ip=($ip)
        IFS=$OIFS
        [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]

        stat=$?
    fi
    return $stat
}

# Подготовка файла inventory
function prepare_inventory_file(){
    if ! ${need_prepare_inventory_file} && ! ${need_default_install}; then
        return
    fi

    if [ ! -f "${INVENTORY_PATH}/sample/inventory.yml" ]; then
        echo -e "${red}Ansible playbook for SoftWLC are not installed on the host${reset}"
        exit 1
    fi

    # Получение адреса хоста
    echo -n "Enter the host address (blank for last used): "
    read swlc_address
    if [ -n "$swlc_address" ]; then
        # Проверка введенного адреса на корректность
        if valid_ipv4 $swlc_address; then
            echo -e "${green}SoftWLC will be configured at the: ${swlc_address}${reset}"
            # Изменение ansible_host в файле inventory с дефолтного на введенный пользователем
            sed -i "s|^\([[:space:]]*ansible_host: *\).*|\1${swlc_address}|" $INVENTORY_PATH/my_softwlc/inventory.yml
        else
            echo -e "${red}Incorrect ip${reset}"
            exit 1
        fi
    fi

    if ! grep "private_key_file" $current_dir/$CURR_FILE_VERSION_NAME/ansible.cfg; then
        echo -e "
${green}Information note${reset}
Ansible uses SSH with existing OS credentials to access machines.
Next, you will be asked to specify the data for connecting via SSH to the previously specified host.
In the future, it is recommended to add the generated ssh key and use it (via \"private_key_file\" in ansible.cfg for example) to increase the security of the connection.
More information (Official Ansible Web site): https://docs.ansible.com/ansible/latest/reference_appendices/config.html
"

        echo -n "Enter SSH user login (blank for last used): "
        read ans
        if [ -n "$ans" ]; then
            sed -i "s|^\([[:space:]]*ansible_user: *\).*|\1${ans}|" $INVENTORY_PATH/my_softwlc/inventory.yml
        fi

        echo -n "Enter SSH user password (blank for last used): "
        read -s ans
        if [ -n "$ans" ]; then
            sed -i "s|^\([[:space:]]*ansible_password: *\).*|\1${ans}|" $INVENTORY_PATH/my_softwlc/inventory.yml
        fi
        echo " "

        echo -n "Enter sudo password (blank for last used): "
        read -s ans
        if [ -n "$ans" ]; then
            sed -i "s|^\([[:space:]]*ansible_become_pass: *\).*|\1${ans}|" $INVENTORY_PATH/my_softwlc/inventory.yml
        fi
        echo " "
    fi
    
    sed -i "s|eltex_hub: .*|eltex_hub: ${ELTEX_DOCKER_REGISTRY}|" $INVENTORY_PATH/my_softwlc/group_vars/all.yml
    
    sed -i "s|ansible_playbook_dir: .*|ansible_playbook_dir: \"${current_dir}/${CURR_FILE_VERSION_NAME}\"|" $INVENTORY_PATH/my_softwlc/group_vars/all.yml
    
    sed -i "s|swlc_version: .*|swlc_version: \"${SOFTWLC_VERSION}\"|" $INVENTORY_PATH/my_softwlc/group_vars/all.yml
    sed -i "s|ems_version: .*|ems_version: \"${EMS_VERSION}\"|" $INVENTORY_PATH/my_softwlc/group_vars/all.yml
    sed -i "s|airtune_version: .*|airtune_version: \"${AIRTUNE_VERSION}\"|" $INVENTORY_PATH/my_softwlc/group_vars/all.yml
}

# ------------------------------------- Start Ansible Docker container --------------------------------------

function start_ansible_container() {
    if ! ${need_start_ansible_container} && ! ${need_default_install}; then
        return
    fi
    echo -e "${green}Starting Ansible docker container${reset}"
    if ! grep "SWLC_VERSION" .env; then
        echo "SWLC_VERSION=${SOFTWLC_VERSION}" >> .env
    fi
    if ! grep "CURR_FILE_VERSION_NAME" .env; then
        echo "CURR_FILE_VERSION_NAME=${CURR_FILE_VERSION_NAME}" >> .env
    fi
    if ! grep "ELTEX_HUB" .env; then
        echo "ELTEX_HUB=${ELTEX_DOCKER_REGISTRY}" >> .env
    fi
    source .env
    docker compose up -d --remove-orphans
}


# ------------------------------------- Migrate configs from debs to docker ---------------------------------

# Миграция из установки в deb в docker
function ansible_migrate_from_debs(){
    if ! ${need_migrate_from_debs}; then
        return
    fi
    sed -i "s|ROOT_DIR_PATH = .*|ROOT_DIR_PATH = ${current_dir}/${CURR_FILE_VERSION_NAME}|" ${current_dir}/${CURR_FILE_VERSION_NAME}/roles/migrate_config_files/files/config.hocon
    echo -e "${green}Migrate configs from debs to docker${reset}"
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_tools.yml -t "migrate-debs"
}

# -------------------------------------- Migrate database create backup -------------------------------------

# Миграция из установки в deb в docker создание бэкапа бд
function ansible_migrate_db_backup(){
    if ! ${need_migrate_backup_db}; then
        return
    fi
    echo -e "${green}Migrate database create backup${reset}"
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_tools.yml -t "migration-backup-db"
}

# ------------------------------------- Migrate database restore backup -------------------------------------

# Миграция из установки в deb в docker восстановление из бэкапа бд
function ansible_migrate_db_restore(){
    if ! ${need_migrate_restore_db}; then
        return
    fi
    echo -e "${green}Migrate database restore backup${reset}"
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_tools.yml -t "migration-restore-db"
}

# ---------------------------------- Install Docker and SoftWLC (default) -----------------------------------

# Установка Docker и SoftWLC (default)
function ansible_install_docker_and_softwlc(){
    if ! ${need_default_install}; then
        return
    fi
    echo -e "${green}Install Docker${reset}"
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_setup.yml -t "install-docker"
    echo -e "${green}Docker installation and configuration complete. Waiting for eltex-ansible to restart...${reset}"
    # Ждём 30 секунд до запуска eltex-ansible
    for ((i=1; i < 7; i++)); do
        if [[ $(docker inspect -f '{{.State.Status}}' "eltex-ansible" 2>/dev/null) == "running" ]]; then
            break
        fi
        sleep 5
    done
    # Если контейнер не запустился - запускаем принудительно
    if [[ $(docker inspect -f '{{.State.Status}}' "eltex-ansible" 2>/dev/null) != "running" ]]; then
        docker compose up -d --remove-orphans
    fi
    # Ждём до запуска eltex-ansible
    while [[ $(docker inspect -f '{{.State.Status}}' "eltex-ansible" 2>/dev/null) != "running" ]]; do
        sleep 5
    done
    echo -e "${green}Install SoftWLC${reset}"
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_setup.yml -t "install-softwlc"
}

# ------------------------------------------- Install Docker ------------------------------------------------

function ansible_install_docker(){
    if ! ${need_install_docker_ansible}; then
        return
    fi
    echo -e "${green}Install Docker${reset}"
    # Запуск плейбука с тегом install-docker
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_setup.yml -t "install-docker"
    echo -e "${green}Docker installation and configuration complete. Waiting for eltex-ansible to restart...${reset}"
    # Ждём 30 секунд до запуска eltex-ansible
    for ((i=1; i < 7; i++)); do
        if [[ $(docker inspect -f '{{.State.Status}}' "eltex-ansible" 2>/dev/null) == "running" ]]; then
            break
        fi
        sleep 5
    done
    # Если контейнер не запустился - запускаем принудительно
    if [[ $(docker inspect -f '{{.State.Status}}' "eltex-ansible" 2>/dev/null) != "running" ]]; then
        docker compose up -d --remove-orphans
    fi
    # Ждём до запуска eltex-ansible
    while [[ $(docker inspect -f '{{.State.Status}}' "eltex-ansible" 2>/dev/null) != "running" ]]; do
        sleep 5
    done
}

# ------------------------------------------- Install SoftWLC ------------------------------------------------

function ansible_install_softwlc(){
    if ! ${need_install_softwlc_ansible}; then
        return
    fi
    echo -e "${green}Install SoftWLC${reset}"
    # Запуск плейбука с тегом install-softwlc
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_setup.yml -t "install-softwlc"
}

# ---------------------------------------------- Ports test --------------------------------------------------

function test_ports(){
    if ! ${need_test_ports}; then
        return
    fi
    echo -e "${green}Test ports${reset}"
    # Запуск плейбука с тегом test-ports
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_setup.yml -t "test-ports"
}

# ------------------------------------------------ Backup ----------------------------------------------------

function create_backup(){
    if ! ${need_backup}; then
        return
    fi
    echo -e "${green}Backup SoftWLC${reset}"
    # Запуск плейбука с тегом backup
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_tools.yml -t "backup"
}

# ------------------------------------------------ Restore ---------------------------------------------------

function restore_backup(){
    if ! ${need_restore}; then
        return
    fi
    echo -e "${green}Restore backup SoftWLC${reset}"
    # Запуск плейбука с тегом restore
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_tools.yml -t "restore"
}

# ----------------------------------------- Run SoftWLC containers -------------------------------------------

function run_containers(){
    if ! ${need_run}; then
        return
    fi
    echo -e "${green}Run SoftWLC${reset}"
    # Запуск плейбука с тегом run
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_tools.yml -t "run"
}

# ---------------------------------------- Stop SoftWLC containers -------------------------------------------

function stop_containers(){
    if ! ${need_stop}; then
        return
    fi
    echo -e "${green}Stop SoftWLC${reset}"
    # Запуск плейбука с тегом stop
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_tools.yml -t "stop"
}

# --------------------------------------- Remove SoftWLC containers ------------------------------------------

function delete_containers(){
    if ! ${need_delete}; then
        return
    fi
    echo -e "${green}Delete SoftWLC containers${reset}"
    # Запуск плейбука с тегом delete
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_tools.yml -t "delete"
}

# -------------------------------------- Recreate SoftWLC containers -----------------------------------------

function recreate_service(){
    local service=${1:?service name is missing}
    echo -e "${green}Recreate ${service} container${reset}"
    # Запуск плейбука с тегом recreate-service и передача ему переменной с названием сервиса
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_tools.yml -t "recreate-service" --extra-vars "containers=['${service_name}']"
}

# -------------------------------------------- Key generation ------------------------------------------------

function generate_keys(){
    if ! ${need_generate_keys}; then
        return
    fi
    echo -e "${green}Generate keys${reset}"
    # Запуск плейбука с тегом generate-keys
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_tools.yml -t "generate-keys"
}

# -------------------------------------------- Password change ------------------------------------------------

function change_password(){
    if ! ${need_change_password}; then
        return
    fi
    echo -e "${green}Change passwords in softwlc${reset}"
    # Запуск плейбука с тегом change-password
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_tools.yml -t "change-password"
}

# ------------------------------------- Update EMS and Airtune licence ----------------------------------------

function update_ems_airtune_licence(){
    if ! ${need_update_ems_airtune_licence}; then
        return
    fi
    echo -e "${green}Update EMS and Airtune licence${reset}"
    # Запуск плейбука с тегом update-ems-airtune-licence
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_tools.yml -t "update-ems-airtune-licence"
}

# ----------------------------------------- Update Wifi-Cab licence --------------------------------------------

function update_wifi_cab_licence(){
    if ! ${need_update_wifi_cab_licence}; then
        return
    fi
    echo -e "${green}Update Wifi-Cab licence${reset}"
    # Запуск плейбука с тегом update-wifi-cab-licence
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_tools.yml -t "update-wifi-cab-licence"
}

# ---------------------------------------- Reconfigure SoftWLC services ----------------------------------------

function reconfigure_softwlc(){
    if ! ${need_reconfigure_softwlc}; then
        return
    fi
    echo -e "${green}Reconfiguring SoftWLC addresses${reset}"
    # Запуск плейбука с тегом reconfigure
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_tools.yml -t "reconfigure"
}

# ---------------------------------------- Configure Radius proxy ----------------------------------------------

function configure_radius_proxy(){
    if ! ${need_configure_radius_proxy}; then
        return
    fi
    echo -e "${green}Configure radius proxy${reset}"
    # Запуск плейбука с тегом configure-radius-proxy
    docker exec -w /ansible -it eltex-ansible ansible-playbook /ansible/softwlc_tools.yml -t "configure-radius-proxy"
}


# --------------------------------- Configure SoftWLC version and repo (For QA test only) ---------------------

function configure_versions(){
    if ! ${need_configure_versions}; then
        return
    fi
    echo -e "${green}Set up SoftWLC versions${reset}"
    
    echo -e "
SoftWLC version:
1. latest (equal ${SOFTWLC_VERSION})
2. other \n"
    echo -n ": "
    
    read ans
    echo ""
    case ${ans} in
    1)
        echo -e "${green}Set to latest ${SOFTWLC_VERSION}${reset}"
        ;;
    2)
        echo -n "Input SoftWLC version (blank for ${SOFTWLC_VERSION}): "
        read ver
        if [ -n "$ver" ]; then
            SOFTWLC_VERSION=${ver}
        fi
        echo -n "Input EMS version (blank for ${EMS_VERSION}): "
        read ver
        if [ -n "$ver" ]; then
            EMS_VERSION=${ver}
        fi
        echo -n "Input Airtune version (blank for ${AIRTUNE_VERSION}): "
        read ver
        echo ""
        if [ -n "$ver" ]; then
            AIRTUNE_VERSION=${ver}
        fi
        echo -e "${green}SoftWLC version: ${SOFTWLC_VERSION}
EMS version: ${EMS_VERSION}
Airtune version: ${AIRTUNE_VERSION}${reset}"
        ;;
    *)
        echo -e "${green}Set to latest ${SOFTWLC_VERSION}${reset}"
        ;;
    esac
    
    echo -e "
Docker registry:
1. ${ELTEX_PUBLIC_REGISTRY}
2. ${ELTEX_PRIVATE_REGISTRY_RELEASE} \n"
    echo -n ": "
    
    read ans
    echo ""
    case ${ans} in
    1)
        echo -e "${green}Set to default ${ELTEX_PUBLIC_REGISTRY}${reset}"
        ;;
    2)
        echo -e "${green}Set to release ${ELTEX_PRIVATE_REGISTRY_RELEASE}${reset}"
        ELTEX_DOCKER_REGISTRY=${ELTEX_PRIVATE_REGISTRY_RELEASE}
        ;;
    *)
        echo -e "${green}Set to default ${ELTEX_PUBLIC_REGISTRY}${reset}"
        ;;
    esac
    
    
    echo -e "
Repository:
1. ${ELTEX_PUBLIC_REPO}
2. ${ELTEX_PRIVATE_REPO} \n"
    echo -n ": "
    
    read ans
    echo ""
    case ${ans} in
    1)
        echo -e "${green}Set to default ${ELTEX_PUBLIC_REPO}${reset}"
        ;;
    2)
        echo -e "${green}Set to private ${ELTEX_PRIVATE_REPO}${reset}"
        ELTEX_REPO=${ELTEX_PRIVATE_REPO}
        ;;
    *)
        echo -e "${green}Set to default ${ELTEX_PUBLIC_REPO}${reset}"
        ;;
    esac
    echo ""
}

# ---------------------------------------------- Show HELP ---------------------------------------------------

function print_help() {
    echo "${help}"
}

# ------------------------------------------ SCRIPT START POINT ----------------------------------------------

# Запрет работы не от root
if [[ $(id -u) -ne 0 ]]; then
    echo -e "${red}This script can only be run as root${reset}"
    exit 1
fi

need_install_docker_host=false
need_start_ansible_container=false
need_install_docker_ansible=false
need_prepare_inventory_file=false
need_migrate_from_debs=false
need_migrate_backup_db=false
need_migrate_restore_db=false
need_install_softwlc_ansible=false
need_test_ports=false
need_backup=false
need_restore=false
need_run=false
need_stop=false
need_delete=false
need_generate_keys=false
need_change_password=false
need_update_ems_airtune_licence=false
need_update_wifi_cab_licence=false
need_reconfigure_softwlc=false
need_configure_radius_proxy=false
need_download_ansible=false
need_configure_versions=false

need_default_install=false

if [[ -n "$1" ]]; then
    while [[ $# -gt 0 ]]; do
        key=$1
        case ${key} in
        --install-docker)
            need_install_docker_host=true
            ;;
        --start-ansible)
            need_start_ansible_container=true
            ;;
        --migrate-from-debs)
            need_download_ansible=true
            need_prepare_inventory_file=true
            need_start_ansible_container=true
            need_migrate_from_debs=true
            ;;
        --migrate-db-backup)
            need_prepare_inventory_file=true
            need_start_ansible_container=true
            need_migrate_backup_db=true
            ;;
        --migrate-db-restore)
            need_prepare_inventory_file=true
            need_start_ansible_container=true
            need_migrate_restore_db=true
            ;;
        --ansible-install-docker)
            need_prepare_inventory_file=true
            need_install_docker_ansible=true
            ;;
        --ansible-install-softwlc)
            need_prepare_inventory_file=true
            need_install_softwlc_ansible=true
            ;;
        --test-ports)
            need_prepare_inventory_file=true
            need_test_ports=true
            ;;
        --backup)
            need_prepare_inventory_file=true
            need_backup=true
            ;;
        --restore)
            need_prepare_inventory_file=true
            need_restore=true
            ;;
        --run)
            need_prepare_inventory_file=true
            need_run=true
            ;;
        --stop)
            need_prepare_inventory_file=true
            need_stop=true
            ;;
        --delete)
            need_prepare_inventory_file=true
            need_delete=true
            ;;
        --generate-keys)
            need_prepare_inventory_file=true
            need_generate_keys=true
            ;;
        --update-ems-licence)
            need_prepare_inventory_file=true
            need_update_ems_airtune_licence=true
            ;;
        --update-wifi-cab-licence)
            need_prepare_inventory_file=true
            need_update_wifi_cab_licence=true
            ;;
        -d | --download)
            need_download_ansible=true
            ;;
        --recreate-service)
            prepare_inventory_file
            shift
            recreate_service $1
            exit 0
            ;;
        --change-password)
            need_prepare_inventory_file=true
            need_change_password=true
            ;;
        --reconfigure)
            need_prepare_inventory_file=true
            need_reconfigure_softwlc=true
            ;;
        --configure-radius-proxy)
            need_prepare_inventory_file=true
            need_configure_radius_proxy=true
            ;;
        --default-install)
            need_default_install=true
            ;;
        -h | --help)
            print_help
            exit 0
            ;;
        *)
            print_help
            exit 0
            ;;
        esac
        shift
    done
else
    # Используется при запуске без ключей
    # Запускаемые функции: check_docker, install_docker, download_softwlc_ansible, prepare_inventory_file, start_ansible_container, ansible_install_docker_and_softwlc
    need_default_install=true
fi

configure_versions

check_docker

install_docker
download_softwlc_ansible
prepare_inventory_file
start_ansible_container

ansible_migrate_from_debs

ansible_install_docker_and_softwlc

ansible_install_docker
ansible_install_softwlc

create_backup
restore_backup

stop_containers
delete_containers
run_containers

ansible_migrate_db_backup
ansible_migrate_db_restore

reconfigure_softwlc

generate_keys
test_ports

configure_radius_proxy
change_password

update_ems_airtune_licence
update_wifi_cab_licence
