#!/bin/bash

# variables section
REPO_TYPE=${1:-stable}
SCRIPTS_URL=https://update.artix.su/static/cs/install_scripts/${REPO_TYPE}/main
DOCKER_FILES_DIRECTORY="/opt/artix/docker/pricechecker/$DOCKER_COMPOSE_NAME"
DOCKER_REGISTRY="docker.artix.su"
DOCKER_REGISTRY_PROTOCOL="http"
REQUIRED_DOCKER_API_VERSION="1.44"
DOCKER_COMPOSE_URL=https://update.artix.su/static/cs/install_scripts/${REPO_TYPE}/pricechecker

if [[ "${REPO_TYPE}" == "stable" ]]; then
    DOCKER_REGISTRY="dockerregistry.artix.su:2443"
    DOCKER_REGISTRY_PROTOCOL="https"
fi

# prepare environment
curl ${SCRIPTS_URL}/import_docker_cert.sh -o /tmp/install_docker_cert.sh
bash /tmp/install_docker_cert.sh
apt install -y jq
if [ -x "$(command -v docker)" ]; then
    echo "Docker already installed"
else
    echo "Install docker"
    curl -O ${SCRIPTS_URL}/install_docker.sh -o /tmp/install_docker.sh
    bash /tmp/install_docker.sh
fi

DOCKER_API_VERSION=$(docker version --format '{{.Server.APIVersion}}' 2>/dev/null)
if dpkg --compare-versions "$DOCKER_API_VERSION" lt "$REQUIRED_DOCKER_API_VERSION"; then
    echo "Внимание: используемая версия Docker Engine API ($DOCKER_API_VERSION) меньше требуемой ($REQUIRED_DOCKER_API_VERSION). Для установки требуется обновить Docker."
    exit 1
fi

DOCKER_MIN_API_VERSION=$(docker version --format '{{.Server.MinAPIVersion}}' 2>/dev/null)
if dpkg --compare-versions "$DOCKER_MIN_API_VERSION" gt "$REQUIRED_DOCKER_API_VERSION"; then
    echo "Ошибка: минимальная версия API установленного Docker Engine ($DOCKER_MIN_API_VERSION) выше требуемой ($REQUIRED_DOCKER_API_VERSION). Установка прервана."
    exit 1
fi


############################
## READ SETTINGS ###########
############################
get_pc_versions() {
    cd /etc/docker/certs.d/dockerregistry.artix.su:2443
    response=$(curl --key client.key --cert client.cert --cacert ca.crt  $DOCKER_REGISTRY_PROTOCOL://$DOCKER_REGISTRY/v2/artix-pricechecker/tags/list)
    if [[ "$REPO_TYPE" == "stable" ]]; then
       version_list="$(echo $response | jq -r '.tags[] | select(test("^[0-9]+\\.[0-9]+\\.[0-9]+$") or test("^[0-9]+\\.[0-9]+$") or test("^[0-9]+$"))')"
    else
      version_list="$(echo $response | jq -r '.tags[]')"
    fi
    sorted_versions=$(echo "$version_list" | sort -V -r)
    echo "${sorted_versions[*]}"
}

versions=( "$(get_pc_versions)" )
read -r -a version_array <<< $(echo $versions)

getOrDefault() {
    local key="$1"
    local default_value="$2"
    local env_file="$DOCKER_FILES_DIRECTORY/.env"

    if [[ ! -f "$env_file" ]]; then
        echo "$default_value"
        return
    fi

    local value=$(grep -E -o "^${key}=[^ ]+" "$env_file" | cut -d '=' -f 2-)

    if [[ -n "$value" ]]; then
        echo "$value"
    else
        echo "$default_value"
    fi
}


VERSION=$(getOrDefault "TAG" $versions[1])
C_VERSION=$VERSION
PORT=$(getOrDefault "SERVER_PORT" "8085")
C_PORT=$PORT
HTTPS_PORT=$(getOrDefault "SSL_SERVER_PORT" "8443")
C_HTTPS_PORT=$HTTPS_PORT
TZ=$(getOrDefault "SET_TIMEZONE" "UTC")
C_TZ=$TZ
LOG=$(getOrDefault "LOG_LEVEL" "INFO")
C_LOG=$LOG

############################
## SECTION: MAIN MENU ######
############################
main_menu() {
    OPTION=$(whiptail --title  "PriceChecker server installer" --menu  "Выберите действие" 20 60 6 \
    "1" "Выбрать версию $( [ $C_VERSION != $VERSION ] && echo "($C_VERSION -> $VERSION)" || echo "($VERSION)" )" \
    "2" "Настроить http порт $( [ $C_PORT != $PORT ] && echo "($C_PORT -> $PORT)" || echo "($PORT)" )" \
    "3" "Настроить https порт $( [ $C_HTTPS_PORT != $HTTPS_PORT ] && echo "($C_HTTPS_PORT -> $HTTPS_PORT)" || echo "($HTTPS_PORT)" )" \
    "4" "Настроить часовой пояс $( [ $C_TZ != $TZ ] && echo "($C_TZ -> $TZ)" || echo "($TZ)" )" \
    "5" "Настроить уровень логирования $( [ $C_LOG != $LOG ] && echo "($C_LOG -> $LOG)" || echo "($LOG)" )" \
    "6" "Применить конфигурацию"  3>&1 1>&2 2>&3)

    exitstatus=$?
    if [ $exitstatus = 0 ]; then
        echo "Выбранная версия: $VERSION"
        if [[ "$OPTION" == "1" ]]; then
           choise_version
        elif [[ "$OPTION" == "2" ]]; then
           input_port
       elif [[ "$OPTION" == "3" ]]; then
           input_https_port
        elif [[ "$OPTION" == "4" ]]; then
           set_tz
        elif [[ "$OPTION" == "5" ]]; then
           choise_log_level
        elif [[ "$OPTION" == "6" ]]; then
           start_update
        else
           echo "Непредвиденное значение"
           exit 1
        fi
    else
        echo "Выбор отменен"
        exit 0
    fi

}
echo "1"

############################
#### FUNC: CHOISE VERSION ##
############################
choise_version() {
    options=()
    isFirst=true
    for version in "${version_array[@]}"; do
        if $isFirst ; then
            options+=("$version artixcs-priceckecker:$version ON")
            isFirst=false
        else
            options+=("$version artixcs-priceckecker:$version  OFF")
        fi
    done

    T_VERSION=$(whiptail --title "Выбрать версию" --radiolist \
        "Выберите версию:" 25 60 10 \
         ${options[@]} 3>&1 1>&2 2>&3)
   
    exitstatus=$?
    if [ $exitstatus = 0 ]; then
       VERSION=$T_VERSION
    fi

    main_menu

}

###########################
#### FUNC: SET TIMEZONE ###
###########################

set_tz() {
   list=$(timedatectl list-timezones)
   options=()
   while IFS= read -r line; do
      options+=("$line" "|")
   done <<< "$list"

   default_index=$(echo "$options" | grep -nE "$TZ" | cut -d: -f1)
   T_TZ=$(whiptail --title "Часовой пояс" --menu "Выберите часовой пояс" 25 78 16 ${options[@]} --default-item "$default_index" --separate-output 3>&1 1>&2 2>&3)

    exitstatus=$?
    if [ $exitstatus = 0 ]; then
       TZ=$T_TZ
    fi

   main_menu
}

###########################
### FUNC: SET LOG LEVEL ###
###########################

choise_log_level() {
    T_LOG=$(whiptail --title "Выбор" --radiolist "Выберите уровень логирования" 15 60 5 \
         "TRACE" "Подробная информация для отладки" $( [ "$LOG" == "TRACE" ] && echo ON || echo OFF ) \
         "DEBUG" "Информация для диагностики проблем" $( [ "$LOG" == "DEBUG" ] && echo ON || echo OFF ) \
         "INFO" "Общие сообщения о работе приложения" $( [ "$LOG" == "INFO" ] && echo ON || echo OFF ) \
         "WARN" "Предупреждения о потенциальных проблемах" $( [ "$LOG" == "WARN" ] && echo ON || echo OFF ) \
         "ERROR" "Ошибки, требующие внимания" $( [ "$LOG" == "ERROR" ] && echo ON || echo OFF )  3>&1 1>&2 2>&3)

    exitstatus=$?
    if [ $exitstatus = 0 ]; then
       LOG=$T_LOG
    fi

    main_menu
}

###########################
#### FUNC: INPUT PORT #####
###########################

input_port() {
    while true; do
        TMP_PORT=$(whiptail --inputbox "Введите порт:" 10 60 "$PORT" 3>&1 1>&2 2>&3)

        exitstatus=$?
        if [ $exitstatus != 0 ]; then
    	    echo "Выход без ввода."
            main_menu
    	    exit
	fi

        if [[ ! "$TMP_PORT" =~ ^[0-9]+$ ]] || [ "$TMP_PORT" -lt 1 ] || [ "$TMP_PORT" -gt 65535 ]; then
            whiptail --msgbox "Неверный порт. Порт должен быть числом в диапазоне 1-65535." 10 60
        else
            PORT=$TMP_PORT
            break
        fi
    done

    main_menu

}

###########################
# FUNC: INPUT HTTPS PORT ##
###########################

input_https_port() {
    while true; do
        TMP_PORT=$(whiptail --inputbox "Введите порт:\nЕсли вы уже установили TWA на устройства, то после смены порта их придется переустановить" 10 60 "$HTTPS_PORT" 3>&1 1>&2 2>&3)

        exitstatus=$?
        if [ $exitstatus != 0 ]; then
    	    echo "Выход без ввода."
            main_menu
    	    exit
	fi

        if [[ ! "$TMP_PORT" =~ ^[0-9]+$ ]] || [ "$TMP_PORT" -lt 1 ] || [ "$TMP_PORT" -gt 65535 ]; then
            whiptail --msgbox "Неверный порт. Порт должен быть числом в диапазоне 1-65535." 10 60
        else
            HTTPS_PORT=$TMP_PORT
            break
        fi
    done

    main_menu

}

##########################
# SECTION: START UPDATE ##
##########################

save_env() {
    if grep -q "^$1=" $DOCKER_FILES_DIRECTORY/.env; then
        sed -i "s/^$1=.*/$1=$2/" $DOCKER_FILES_DIRECTORY/.env
    else
        echo "$1=$2" >> $DOCKER_FILES_DIRECTORY/.env
    fi
}

start_update() {
    mkdir -p $DOCKER_FILES_DIRECTORY
    cd $DOCKER_FILES_DIRECTORY

    save_env "SERVER_PORT" "$PORT"
    save_env "TAG" "$VERSION"
    save_env "LOG_LEVEL" "$LOG"
    save_env "SET_TIMEZONE" $(echo "$TZ" | sed 's/\//\\\//g')
    save_env "DOCKER_REGISTRY" "$DOCKER_REGISTRY"
    save_env "SSL_SERVER_PORT" "$HTTPS_PORT"

    wget -q -O "./docker-compose.yaml" "$DOCKER_COMPOSE_URL/docker-compose.yaml"

    docker compose up -d

   echo "Конфигурация успешно применена"
}

main_menu