#!/bin/bash

# Author: Tomi Eckert
# --- Main Script ---

# This script presents a menu of software packages, or installs them
# non-interactively via command-line arguments. It downloads files from a
# remote configuration, shows a diff for config updates, and checks versions.

# --- Functions ---

# Get the version from a local script file.
get_local_version() {
    local file_path="$1"
    if [[ -f "${file_path}" ]]; then
        head -n 5 "${file_path}" | grep -m 1 "^# Version:" | awk '{print $NF}'
    else
        echo "0.0.0" # Return a base version if file doesn't exist.
    fi
}

# Compare two version strings. Returns 0 if v1 is newer.
is_version_greater() {
    local v1=$1
    local v2=$2
    if [[ "$(printf '%s\n' "$v1" "$v2" | sort -V | head -n 1)" != "$v1" ]]; then
        return 0 # v1 is greater
    else
        return 1 # v1 is not greater (equal or less)
    fi
}

# Process a single selected package.
process_package() {
    local choice_key="$1"
    local force_overwrite="$2" # Expects "true" or "false"

    if [[ -z "${SCRIPT_PACKAGES[$choice_key]}" ]]; then
        echo "[❌] Invalid package name provided: '${choice_key}'"
        return
    fi

    echo
    echo "[⬇️] Processing package: '${choice_key}'..."

    # Parse the new config format
    config_value="${SCRIPT_PACKAGES[$choice_key]}"
    display_name=$(echo "${config_value}" | cut -d'|' -f1)
    remote_version=$(echo "${config_value}" | cut -d'|' -f2)
    description=$(echo "${config_value}" | cut -d'|' -f3)
    urls_to_download=$(echo "${config_value}" | cut -d'|' -f4)
    install_script=$(echo "${config_value}" | cut -d'|' -f5) # Optional install script

    read -r -a urls_to_download_array <<< "$urls_to_download"

    for url in "${urls_to_download_array[@]}"; do
        filename=$(basename "${url}")
        # Handle config file overwrites
        if [[ "${filename}" == *.conf && -f "${filename}" ]]; then
            if [[ "$force_overwrite" == "true" ]]; then
                echo "[⚠️] Overwriting '${filename}' due to --overwrite-config flag."
                if ! curl -fsSL -o "${filename}" "${url}"; then
                     echo "[❌] Error: Failed to download '${filename}'."
                fi
                continue
            fi

            echo "[->] Found existing config file: '${filename}'."
            tmp_file=$(mktemp)
            if curl -fsSL -o "${tmp_file}" "${url}"; then
                echo "[🔎] Comparing versions..."
                echo "-------------------- DIFF START --------------------"
                if command -v colordiff &> /dev/null; then
                    colordiff -u "${filename}" "${tmp_file}"
                else
                    diff --color=always -u "${filename}" "${tmp_file}" 2>/dev/null || diff -u "${filename}" "${tmp_file}"
                fi
                echo "--------------------- DIFF END ---------------------"
                read -p "Do you want to overwrite '${filename}'? (y/N) " -n 1 -r REPLY
                echo
                if [[ $REPLY =~ ^[Yy]$ ]]; then
                    mv "${tmp_file}" "${filename}"
                    echo "[✅] Updated '${filename}'."
                else
                    rm "${tmp_file}"
                    echo "[🤷] Kept existing version of '${filename}'."
                fi
            else
                echo "[❌] Error downloading new version of '${filename}' for comparison."
                rm -f "${tmp_file}"
            fi
        else
            # Original download logic for all other files.
            echo "[->] Downloading '${filename}'..."
            if curl -fsSL -o "${filename}" "${url}"; then
                echo "[✅] Successfully downloaded '${filename}'."
                if [[ "${filename}" == *.sh || "${filename}" == *.bash ]]; then
                    chmod +x "${filename}"
                    echo "[🤖] Made '${filename}' executable."
                fi
            else
                echo "[❌] Error: Failed to download '${filename}'."
            fi
        fi
    done

    if [[ -n "${install_script}" ]]; then
        echo "[⚙️] Running install script for '${choice_key}'..."
        #eval "${install_script}"
        bash -c "$(curl -sSL $install_script)"
        if [ $? -eq 0 ]; then
            echo "[✅] Install script completed successfully."
        else
            echo "[❌] Install script failed with exit code $?."
        fi
    fi
    echo "[📦] Package processing complete for '${choice_key}'."
}

# --- Main Logic ---

conf_file="packages.conf.$(date +%Y%m%d%H%M%S)"
trap 'rm -f "${conf_file}"' EXIT

echo "[🔄] Downloading configuration file..."
if ! curl -fsSL -o "${conf_file}" "https://git.technopunk.space/tomi/Scripts/raw/branch/main/packages.conf"; then
    echo "[❌] Error: Failed to download packages.conf. Exiting."
    exit 1
fi
echo "[✅] Configuration file downloaded successfully."

source "${conf_file}"

# --- Argument Parsing for Non-Interactive Mode ---
if [ "$#" -gt 0 ]; then
    declare -a packages_to_install
    overwrite_configs=false
    for arg in "$@"; do
        case $arg in
            --overwrite-config)
            overwrite_configs=true
            ;;
            -*)
            echo "[❌] Unknown flag: $arg" >&2
            exit 1
            ;;
            *)
            packages_to_install+=("$arg")
            ;;
        esac
    done

    if [ ${#packages_to_install[@]} -eq 0 ]; then
        echo "[❌] Flag provided with no package names. Exiting."
        exit 1
    fi

    echo "[🚀] Running in non-interactive mode."
    for pkg_key in "${packages_to_install[@]}"; do
        if [[ -n "${SCRIPT_PACKAGES[$pkg_key]}" ]]; then
            process_package "$pkg_key" "$overwrite_configs"
        else
            echo "[⚠️] Unknown package: '$pkg_key'. Skipping."
        fi
    done
    echo "[🏁] Non-interactive run complete."
    exit 0
fi

# --- Interactive Mode ---
declare -a ordered_keys
package_keys_sorted=($(for k in "${!SCRIPT_PACKAGES[@]}"; do echo $k; done | sort))
ordered_keys=("${package_keys_sorted[@]}")

# --- Display Menu ---
echo
echo "-------------------------------------"
echo "        Script Downloader            "
echo "-------------------------------------"
echo "[🔎] Checking for updates..."
echo

for i in "${!ordered_keys[@]}"; do
    key="${ordered_keys[$i]}"
    config_value="${SCRIPT_PACKAGES[$key]}"
    display_name=$(echo "${config_value}" | cut -d'|' -f1)
    remote_version=$(echo "${config_value}" | cut -d'|' -f2)
    description=$(echo "${config_value}" | cut -d'|' -f3)
    urls=$(echo "${config_value}" | cut -d'|' -f4)
    # install_script=$(echo "${config_value}" | cut -d'|' -f5) # Not used for display in menu
    read -r -a url_array <<< "$urls"
    main_script_filename=$(basename "${url_array[0]}")
    local_version=$(get_local_version "${main_script_filename}")

    # Print main package line
    echo -e "\033[1m$((i+1))) $key - $display_name (v$remote_version)\033[0m"
    # Print description
    echo "   $description"
    # Print status
    if [[ -f "${main_script_filename}" ]]; then
        if is_version_greater "$remote_version" "$local_version"; then
            echo -e "   \033[33m[Update available: v${local_version} -> v${remote_version}]\033[0m"
        else
            echo -e "   \033[32m[Installed: v${local_version}]\033[0m"
        fi
    fi
    echo
done
quit_num=$((${#ordered_keys[@]} + 1))
echo -e "\033[1m${quit_num}) Quit\033[0m"
echo

# --- Handle User Input ---
read -p "Please enter your choice(s) (e.g., 1 3 4), or press Enter to quit: " -r -a user_choices

if [ ${#user_choices[@]} -eq 0 ]; then
    echo "[👋] No selection made. Exiting."
    exit 0
fi

for choice_num in "${user_choices[@]}"; do
    if ! [[ "$choice_num" =~ ^[0-9]+$ ]]; then
        echo "[⚠️] Skipping invalid input: '${choice_num}'. Not a number."
        continue
    fi
    if [ "$choice_num" -eq "$quit_num" ]; then
        echo "[👋] Quit selected. Exiting."
        exit 0
    fi
    index=$((choice_num - 1))
    if [[ -z "${ordered_keys[$index]}" ]]; then
        echo "[⚠️] Skipping invalid choice: '${choice_num}'. Out of range."
        continue
    fi
    choice_key="${ordered_keys[$index]}"
    process_package "$choice_key" "false" # Never force overwrite in interactive mode
done

echo
echo "[🏁] All selected packages have been processed."

