#!/bin/bash
# shellcheck shell=bash
# updateOllama: Lädt und installiert die aktuelle Ollama-Version (stable oder beta).

set -euo pipefail
shopt -s nullglob

readonly GITHUB_API="https://api.github.com/repos/ollama/ollama"
readonly INSTALL_URL="https://ollama.com/install.sh"
PROG_NAME=$(basename "$0") || { printf 'Fehler: basename fehlgeschlagen\n' >&2; exit 1; }
readonly PROG_NAME

usage() {
    printf 'Verwendung: %s [--beta|-b]\n' "$PROG_NAME" >&2
    exit 2
}

check_dependencies() {
    local cmd
    for cmd in curl grep sed sort mktemp chmod; do
        if ! command -v "$cmd" >/dev/null 2>&1; then
            die "Benötigtes Kommando '$cmd' nicht gefunden."
        fi
    done
}

die() {
    printf 'Fehler: %s\n' "$1" >&2
    exit "${2:-1}"
}

parse_args() {
    local use_beta=false

    while [[ $# -gt 0 ]]; do
        case "$1" in
            --beta|-b) use_beta=true ;;
            -h|--help) usage ;;
            *) usage ;;
        esac
        shift
    done

    printf '%s\n' "$use_beta"
}

get_local_version() {
    local version_line
    if ! version_line=$(ollama --version 2>/dev/null); then
        return 0
    fi

    printf '%s\n' "$version_line" | grep -oEm1 '[0-9]+\.[0-9]+\.[0-9]+[^[:space:]]*' || true
}

# Helfer: GitHub-API abrufen und sicherstellen, dass die Antwort nicht leer ist.
fetch_github_json() {
    local url=$1
    local response

    if ! response=$(curl -fsSL "$url"); then
        die "API-Anfrage fehlgeschlagen: $url"
    fi

    if [[ -z "$response" ]]; then
        die "API-Antwort war leer: $url"
    fi

    printf '%s\n' "$response"
}

get_latest_version() {
    local url=$1
    local json

    json=$(fetch_github_json "$url")
    printf '%s\n' "$json" | sed -nE 's/.*"tag_name": *"v?([^"]+)".*/\1/p' | head -n1
}

# Vergleicht zwei Versionsstrings (SemVer-ähnlich, Suffixe alphabetisch).
# Gibt -1, 0 oder 1 aus.
cmp_versions() {
    local a=${1#v} b=${2#v}
    local a_main=${a%%-*} b_main=${b%%-*}
    local a_parts b_parts
    local max_len i

    IFS=. read -r -a a_parts <<< "$a_main"
    IFS=. read -r -a b_parts <<< "$b_main"

    max_len=${#a_parts[@]}
    if (( ${#b_parts[@]} > max_len )); then
        max_len=${#b_parts[@]}
    fi

    for (( i=0; i<max_len; i++ )); do
        local av=$((10#${a_parts[i]:-0}))
        local bv=$((10#${b_parts[i]:-0}))

        if (( av < bv )); then
            printf '%s\n' -1
            return 0
        elif (( av > bv )); then
            printf '%s\n' 1
            return 0
        fi
    done

    local a_suffix=${a#*-} b_suffix=${b#*-}
    [[ "$a_suffix" == "$a_main" ]] && a_suffix=""
    [[ "$b_suffix" == "$b_main" ]] && b_suffix=""

    if [[ -z "$a_suffix" && -z "$b_suffix" ]]; then
        printf '%s\n' 0
        return 0
    fi
    if [[ -z "$a_suffix" ]]; then
        printf '%s\n' 1
        return 0
    fi
    if [[ -z "$b_suffix" ]]; then
        printf '%s\n' -1
        return 0
    fi

    if [[ "$a_suffix" == "$b_suffix" ]]; then
        printf '%s\n' 0
        return 0
    fi

    if [[ "$(printf '%s\n' "$a_suffix" "$b_suffix" | sort -V | head -n1)" == "$a_suffix" ]]; then
        printf '%s\n' -1
    else
        printf '%s\n' 1
    fi
}

install_ollama() {
    local version=$1
    local tmp_script
    tmp_script=$(mktemp "${TMPDIR:-/tmp}/ollama-install.XXXXXX")

    # Temporäre Datei beim Beenden oder Abbruch aufräumen.
    trap 'rm -f "$tmp_script"' EXIT

    printf 'Lade Installations-Skript herunter ...\n'
    curl -fsSL "$INSTALL_URL" -o "$tmp_script" || die "Herunterladen von $INSTALL_URL fehlgeschlagen."

    if [[ ! -s "$tmp_script" ]]; then
        die "Installations-Skript ist leer."
    fi

    if [[ -n "$version" ]]; then
        export OLLAMA_VERSION="$version"
    fi

    # Skript ausführbar machen und ausführen.
    chmod +x "$tmp_script" || die "Konnte Installations-Skript nicht ausführbar machen."
    "$tmp_script" || die "Installation von Ollama ist fehlgeschlagen."
}

main() {
    local use_beta=false
    local local_ver stable_ver beta_ver
    local target_ver=""

    use_beta=$(parse_args "$@")
    check_dependencies

    local_ver=$(get_local_version)

    # Nur benötigte API-Daten abrufen.
    stable_ver=$(get_latest_version "$GITHUB_API/releases/latest")
    if [[ -z "$stable_ver" ]]; then
        die "Ermittlung der aktuellen Stable-Version fehlgeschlagen."
    fi

    if [[ "$use_beta" == true ]]; then
        beta_ver=$(get_latest_version "$GITHUB_API/releases?per_page=1")
        if [[ -z "$beta_ver" ]]; then
            die "Ermittlung der aktuellen Beta-Version fehlgeschlagen."
        fi
    else
        beta_ver="$stable_ver"
    fi

    printf 'Lokal:  %s\n' "${local_ver:-(nicht installiert)}"
    printf 'Stable: %s\n' "$stable_ver"

    if [[ "$use_beta" == true ]] && [[ "$(cmp_versions "$beta_ver" "$stable_ver")" == 1 ]]; then
        printf 'Beta:   %s\n' "$beta_ver"
    else
        printf 'Beta:   keine neuere Beta verfuegbar\n'
    fi

    if [[ -z "$local_ver" ]]; then
        # Keine lokale Installation.
        if [[ "$use_beta" == true ]] && [[ "$(cmp_versions "$beta_ver" "$stable_ver")" == 1 ]]; then
            target_ver="$beta_ver"
            printf 'Ollama ist nicht installiert. Installation der Beta %s.\n' "$target_ver"
        else
            target_ver="$stable_ver"
            printf 'Ollama ist nicht installiert. Installation der Stable %s.\n' "$target_ver"
        fi
    else
        # Lokale Installation vorhanden.
        if [[ "$use_beta" == true ]]; then
            if [[ "$(cmp_versions "$beta_ver" "$stable_ver")" == 1 ]] \
                && [[ "$(cmp_versions "$beta_ver" "$local_ver")" == 1 ]]; then
                target_ver="$beta_ver"
                printf 'Beta-Update verfuegbar: %s -> %s\n' "$local_ver" "$target_ver"
            elif [[ "$(cmp_versions "$stable_ver" "$local_ver")" == 1 ]]; then
                target_ver="$stable_ver"
                printf 'Stable-Update verfuegbar: %s -> %s\n' "$local_ver" "$target_ver"
            else
                printf 'Kein Update erforderlich.\n'
                return 0
            fi
        else
            if [[ "$(cmp_versions "$stable_ver" "$local_ver")" == 1 ]]; then
                target_ver="$stable_ver"
                printf 'Update verfuegbar: %s -> %s\n' "$local_ver" "$target_ver"
            else
                printf 'Kein Update erforderlich.\n'
                return 0
            fi
        fi
    fi

    # Bei Beta-Installation die gewünschte Version an das Installer-Skript übergeben.
    if [[ "$use_beta" == true && -n "$target_ver" && "$target_ver" != "$stable_ver" ]]; then
        install_ollama "$target_ver"
    else
        install_ollama ""
    fi
}

main "$@"
