#!/bin/bash

source /opt/durapps/spark-store/bin/bashimport/transhell.amber
load_transhell_debug

#############################################################

function has-command() {
    command -v "$1" >/dev/null 2>&1
}

# 发送通知
function notify-send() {
    local user
    user=$(detect-notify-user)

    if [ -z "$user" ]; then
        return 1
    fi

    # Detect uid of the user
    local uid=$(id -u $user)

    sudo -u $user  DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${uid}/bus notify-send "$@"
}

function detect-notify-user() {
    local user

    user=$(who | awk '{print $1}' | head -n 1)
    if [ -n "$user" ]; then
        echo "$user"
        return 0
    fi

    if command -v loginctl >/dev/null 2>&1; then
        user=$(loginctl list-sessions --no-legend 2>/dev/null | awk 'NR == 1 {print $3}')
        if [ -n "$user" ]; then
            echo "$user"
            return 0
        fi
    fi

    return 1
}

function load-ignored-apps() {
    declare -gA ignored_apps=()
    local config_paths=()
    declare -A seen_config_paths=()
    local user
    local user_home
    local config_path

    user=$(detect-notify-user)
    if [ -n "$user" ]; then
        user_home=$(getent passwd "$user" | cut -d: -f6)
        if [ -n "$user_home" ] && [ -d "$user_home" ]; then
            config_path="$user_home/.config/spark-store/ignored_apps.conf"
            if [ -f "$config_path" ] && [ -z "${seen_config_paths["$config_path"]}" ]; then
                config_paths+=("$config_path")
                seen_config_paths["$config_path"]=1
            fi
        fi
    fi

    local home_dir
    for home_dir in /home/*; do
        if [ ! -d "$home_dir" ]; then
            continue
        fi

        config_path="$home_dir/.config/spark-store/ignored_apps.conf"
        if [ -f "$config_path" ] && [ -z "${seen_config_paths["$config_path"]}" ]; then
            config_paths+=("$config_path")
            seen_config_paths["$config_path"]=1
        fi
    done

    local pkg_name
    local pkg_version
    for config_path in "${config_paths[@]}"; do
        while IFS='|' read -r pkg_name pkg_version || [ -n "$pkg_name" ]; do
            pkg_name=$(printf '%s' "$pkg_name" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
            pkg_version=$(printf '%s' "$pkg_version" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
            if [ -n "$pkg_name" ] && [ -n "$pkg_version" ]; then
                ignored_apps["$pkg_name|$pkg_version"]=1
            fi
        done < "$config_path"
    done
}

function get-apm-upgradable-list() {
    local output
    output=$(env LANGUAGE=en_US apm list --upgradable 2>/dev/null | awk 'NR>1')

    local ifs_old="$IFS"
    IFS=$'\n'

    local line
    for line in $output; do
        local pkg_name
        local pkg_new_ver
        local pkg_cur_ver
        pkg_name=$(echo "$line" | awk -F '/' '{print $1}')
        pkg_new_ver=$(echo "$line" | awk '{print $2}')
        pkg_cur_ver=$(printf '%s\n' "$line" | sed -n 's/.*\[\(upgradable from\|from\):[[:space:]]*\([^]]*\)\].*/\2/p')

        if [ -n "$pkg_name" ] && [ -n "$pkg_new_ver" ] && [ -n "$pkg_cur_ver" ]; then
            echo "${pkg_name} ${pkg_new_ver} ${pkg_cur_ver}"
        fi
    done

    IFS="$ifs_old"
}

# 检测网络链接畅通
function network-check() {
    # 超时时间
    local timeout=15

    # 目标网站
    local target=www.baidu.com

    # 获取响应状态码
    local ret_code=$(curl -I -s --connect-timeout ${timeout} ${target} -w %{http_code} | tail -n1)

    if [ "$ret_code" = "200" ]; then
        # 网络畅通
        return 0
    else
        # 网络不畅通
        return 1
    fi
}

has_aptss=0
has_apm=0

if has-command aptss; then
    has_aptss=1
fi

if has-command apm; then
    has_apm=1
fi

if [ "$has_aptss" -eq 0 ] && [ "$has_apm" -eq 0 ]; then
    exit 0
fi

# 初始化等待时间和最大等待时间
initial_wait_time=15  # 初始等待时间 15 秒
max_wait_time=$((12 * 3600))  # 最大等待时间 12 小时

# 检测网络，若不通则进行重试，采用指数退避算法
wait_time=$initial_wait_time
while ! network-check; do
    echo "$TRANSHELL_CONTENT_NETWORK_FAIL"
    echo "Waiting for network to recover... Retrying in ${wait_time} seconds."

    sleep $wait_time
    wait_time=$((wait_time * 2))  # 等待时间翻倍
    if [ $wait_time -gt $max_wait_time ]; then
        wait_time=$max_wait_time  # 最大等待时间限制为12小时
    fi
done

load-ignored-apps
spark_update_count=0
if [ "$has_aptss" -eq 1 ]; then
    # 每日更新星火源文件
    aptss update

    updatetext=$(LANGUAGE=en_US aptss ssupdate 2>&1)

    # 在网络恢复后，继续更新操作
    retry_count=0
    max_retries=12  # 最大重试次数，防止死循环

    until ! echo "$updatetext" | grep -q "E:"; do
        if [ $retry_count -ge $max_retries ]; then
            echo "Reached maximum retry limit for aptss ssupdate."
            exit 1
        fi

        echo "${TRANSHELL_CONTENT_UPDATE_ERROR_AND_WAIT_15_SEC}"
        sleep 15
        updatetext=$(LANGUAGE=en_US aptss ssupdate 2>&1)
        retry_count=$((retry_count + 1))
    done

    spark_update_count=$(env LANGUAGE=en_US /usr/bin/apt -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf list --upgradable -o Dir::Etc::sourcelist="/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/aptss.list" -o Dir::Etc::sourceparts="/dev/null" -o APT::Get::List-Cleanup="0" 2>/dev/null | grep -c upgradable)

    if [ "$spark_update_count" -gt 0 ]; then
        # 获取用户选择的要更新的应用
        PKG_LIST="$(/opt/durapps/spark-store/bin/update-upgrade/ss-do-upgrade-worker.sh upgradable-list)"
        IFS_OLD="$IFS"
        IFS=$'\n'

        for line in $PKG_LIST; do
            PKG_NAME=$(echo "$line" | awk -F ' ' '{print $1}')
            PKG_NEW_VER=$(echo "$line" | awk -F ' ' '{print $2}')
            PKG_CUR_VER=$(echo "$line" | awk -F ' ' '{print $3}')

            dpkg --compare-versions "$PKG_NEW_VER" le "$PKG_CUR_VER"
            if [ $? -eq 0 ]; then
                spark_update_count=$((spark_update_count - 1))
                continue
            fi

            PKG_STA=$(dpkg-query -W -f='${db:Status-Want}' "$PKG_NAME")
            if [ "$PKG_STA" = "hold" ]; then
                spark_update_count=$((spark_update_count - 1))
                continue
            fi

            if [ -n "${ignored_apps["$PKG_NAME|$PKG_NEW_VER"]}" ]; then
                spark_update_count=$((spark_update_count - 1))
                continue
            fi
        done

        IFS="$IFS_OLD"
    fi
fi

apm_update_count=0
if [ "$has_apm" -eq 1 ]; then
    updatetext=$(LANGUAGE=en_US apm update 2>&1)
    retry_count=0
    max_retries=12

    until ! echo "$updatetext" | grep -q "E:"; do
        if [ $retry_count -ge $max_retries ]; then
            echo "Reached maximum retry limit for apm update."
            exit 1
        fi

        echo "Update failed...Will retry in 15sec"
        sleep 15
        updatetext=$(LANGUAGE=en_US apm update 2>&1)
        retry_count=$((retry_count + 1))
    done

    apm clean
    PKG_LIST="$(get-apm-upgradable-list)"
    apm_update_count=$(printf '%s\n' "$PKG_LIST" | awk 'NF { count++ } END { print count + 0 }')

    if [ "$apm_update_count" -gt 0 ]; then
        IFS_OLD="$IFS"
        IFS=$'\n'

        for line in $PKG_LIST; do
            PKG_NAME=$(echo "$line" | awk -F ' ' '{print $1}')
            PKG_NEW_VER=$(echo "$line" | awk -F ' ' '{print $2}')
            PKG_CUR_VER=$(echo "$line" | awk -F ' ' '{print $3}')

            amber-pm-debug dpkg --compare-versions "$PKG_NEW_VER" le "$PKG_CUR_VER"
            if [ $? -eq 0 ]; then
                apm_update_count=$((apm_update_count - 1))
                continue
            fi

            PKG_STA=$(amber-pm-debug dpkg-query -W -f='${db:Status-Want}' "$PKG_NAME")
            if [ "$PKG_STA" = "hold" ]; then
                apm_update_count=$((apm_update_count - 1))
                continue
            fi

            if [ -n "${ignored_apps["$PKG_NAME|$PKG_NEW_VER"]}" ]; then
                apm_update_count=$((apm_update_count - 1))
                continue
            fi
        done

        IFS="$IFS_OLD"
    fi
fi

update_app_number=$((spark_update_count + apm_update_count))
if [ "$update_app_number" -le 0 ]; then
    exit 0
fi
update_transhell

# 如果都是hold或者版本一致的那就直接退出，否则把剩余的给提醒了
# TODO: 除了apt-mark hold之外额外有一个禁止检查列表
# 如果不想提示就不提示

user=$(detect-notify-user)
if [ -n "$user" ] && [ -e "/home/$user/.config/spark-union/spark-store/ssshell-config-do-not-show-upgrade-notify" ]; then
    echo "他不想站在世界之巅，好吧"
    echo "Okay he don't want to be at the top of the world, okay"
    exit
else
    notify-send -a spark-store "${TRANSHELL_CONTENT_SPARK_STORE_UPGRADE_NOTIFY}" "${TRANSHELL_CONTENT_THERE_ARE_APPS_TO_UPGRADE}" || true # Some machine don't have bus, or who command just print nothing.
fi
