#!/usr/bin/env bash

CLN_REGISTER_SERVER="https://cln.cloudlinux.com/cln/api/els/server/register"
CLN_UNREGISTER_SERVER="https://cln.cloudlinux.com/cln/api/els/server/unregister"
LICENSE=""
HOSTNAME=`hostname`
AUTH_CONF_PATH="/etc/yum/vars/elstoken"
LEGACY_REPO_PATH="/etc/yum.repos.d/centos8stream-els.repo"
PACKAGE_URI="https://repo.tuxcare.com/centos8stream-els/els-os-release-install.el8.x86_64.rpm"

show_usage() {
    echo 'Usage: install-centos8stream-els-repo.sh [OPTION]...'
    echo ''
    echo '  -l, --license-key   User license key'
    echo '  -f, --force         Force re-register if ELS is already installed'
    echo '  -d, --delete        Delete ELS from server'
    echo '  -v, --validate      Check if ELS is installed'
    echo '  -h, --help          Show this message and exit'
}

els_installed() {
    echo "Checking if ELS is already installed... "

    # Check for new installation method (els-os-release package). Query the rpmdb
    # directly instead of `yum list installed`: on a post-EOL host the stock
    # BaseOS/AppStream mirrors are unreachable and a metadata refresh would fail
    # before yum could answer the question.
    if rpm -q --quiet els-os-release; then
        echo "els-os-release package is already installed."
        return 0
    fi

    # Check for old installation method (elstoken file and repo files)
    if [[ -f "$AUTH_CONF_PATH" || -f "$LEGACY_REPO_PATH" ]]; then
        echo "ELS is installed using the old installation method."
        return 0
    fi

    return 1
}

get_current_token() {
    # Both the package-based and the legacy install keep the token in the
    # elstoken yum variable; the legacy repo file referenced it as $elstoken
    # rather than embedding the value, so there is nothing else to parse.
    if [[ -f "$AUTH_CONF_PATH" ]]; then
        cat "$AUTH_CONF_PATH"
    fi
}

# Returns: 0 - unregistered, 1 - unregister failed, 2 - no token found
unregister_server() {
    TOKEN=$(get_current_token)
    if [[ -z "$TOKEN" ]]; then
        echo "No token found - server may not be registered"
        return 2
    fi

    echo "Attempting to unregister server..."
    CLN_UNREGISTER=$(curl -i -s -X POST "$CLN_UNREGISTER_SERVER?token=$TOKEN")
    CLN_UNREGISTER_CODE=$(head -n1 <<< "$CLN_UNREGISTER")
    if [[ "$CLN_UNREGISTER_CODE" == *"200"* ]]; then
        echo "Server unregistered successfully"
        return 0
    fi

    echo "Warning: Failed to unregister server: $CLN_UNREGISTER"
    return 1
}

install_els_os_release() {
    TEMP_RPM=$(mktemp /tmp/els-os-release-XXXXXX.rpm)

    trap 'rm -f "$TEMP_RPM"' EXIT

    if ! curl -fsSL -o "$TEMP_RPM" "$PACKAGE_URI"; then
        echo "Error: Couldn't download els-os-release.rpm"
        exit 1
    fi

    # els-os-release ships only the .repo file and the GPG key and depends on
    # nothing outside rpmlib, so it needs no repository to resolve against.
    # Keep every repo disabled: on a post-EOL CentOS 8 host the stock mirrors
    # are dead and the metadata refresh would abort the install before
    # els-define is ever reached.
    if ! yum install -y --disablerepo='*' "$TEMP_RPM"; then
        echo "Error: Couldn't install els-os-release"
        exit 3
    fi
}

remove_els_installation() {
    # Remove the ELS marker package installed from the ELS repo
    if rpm -q --quiet els-define; then
        echo "Removing els-define package... "
        if yum remove -y --disablerepo='*' els-define; then
            echo "Ok"
        else
            echo "Error (Could not remove els-define package)"
            exit 1
        fi
    fi

    # Remove new installation method (els-os-release package)
    if rpm -q --quiet els-os-release; then
        echo "Removing els-os-release package... "
        if yum remove -y --disablerepo='*' els-os-release; then
            echo "Ok"
        else
            echo "Error (Could not remove els-os-release package)"
            exit 1
        fi
    fi

    # Remove old installation method files
    echo "Removing authentication configuration file... "
    if rm -f "$AUTH_CONF_PATH"; then
        echo "Ok"
    else
        echo "Error (Could not remove auth configuration file: $AUTH_CONF_PATH)"
        exit 1
    fi

    echo "Removing old repository configuration files... "
    if ! rm -f "$LEGACY_REPO_PATH"; then
        echo "Error (Could not remove centos8stream-els.repo)"
        exit 1
    fi
}

if [[ $# -eq 0 ]]; then
    echo "An option should be specified. See usage -h, --help."
    exit 1
fi


check_superuser_privileges() {
    echo "Checking for superuser privileges..."
    if [ "$(id -u)" -ne 0 ]; then
        echo "Error: This script must be run with superuser privileges"
        return 1
    fi
    echo "Superuser privileges confirmed"
    return 0
}

for opt in "$@"; do
    case ${opt} in
        -l|--license-key)
            if [[ -z "$2" || "$2" == -* ]]; then
                echo "Error: --license-key requires an argument"
                show_usage
                exit 1
            fi
            LICENSE=$2 ; shift ;;
        -f|--force)
            FORCE=true ; shift ;;
        -d|--delete)
            DELETE=true ; shift ;;
        -v|--validate)
            VALIDATE=true ; shift ;;
        -h|--help)
            show_usage ; exit 0 ;;
        -*|--*)
            echo; echo "Unrecognized option: ${opt}"; show_usage ; exit 1 ;;
    esac
done

if ! check_superuser_privileges; then
    exit 14
fi

if [[ -n $VALIDATE ]]; then
    if els_installed; then
        TOKEN=$(get_current_token)
        if [[ -n "$TOKEN" ]]; then
            echo "Server is registered with token $TOKEN"
        else
            echo "Server is registered but token was not found"
        fi
        exit 0
    else
        echo "Server is not registered"
        exit 1
    fi
fi

if [[ -n $DELETE ]]; then
    # Attempt to unregister from server (if token exists)
    unregister_server
    UNREGISTER_RC=$?

    # Remove ELS installation regardless of unregistration status
    echo "Removing ELS installation..."
    if ! remove_els_installation; then
        exit 1
    fi

    if [[ $UNREGISTER_RC -eq 0 ]]; then
        echo "CentOS ELS deleted successfully"
    elif [[ $UNREGISTER_RC -eq 2 ]]; then
        echo "CentOS ELS removed successfully (server was not registered)"
    else
        echo "CentOS ELS removed successfully, but the server could not be unregistered from CLN"
    fi
    exit
fi

# check centos-release file
if [[ ! -f /etc/centos-release ]]; then
    echo "This server is not RHEL based"
    exit 1
fi

# check centos version
centos_release="$(cat /etc/centos-release)"
if [[ ! "${centos_release}" == *"CentOS Stream release 8"* ]]; then
    echo "This server is not CentOS Stream release 8"
    exit 1
fi

# check license key
if [[ -z $LICENSE ]]; then
    echo "License key should be specified with -l, --license-key."
    echo "See -h, --help."
    exit 1
fi

# The license key is validated before anything is touched: --force must never
# tear down a working installation only to fail on a missing or bad key.
if [[ -n $FORCE ]]; then
    # Force reinstall: release the old token (if any) and remove any previous
    # installation, complete or partial, then proceed as a fresh install
    unregister_server
    if ! remove_els_installation; then
        exit 1
    fi
elif els_installed; then
    echo "This server has already installed ELS repo and token"
    echo "For re-registration license run script with --force"
    exit 1
fi

# get token
CLN_REGISTER=$(curl -i -X POST -H "Content-Type: application/json" -H "accept: */*" -d "{\"key\": \"$LICENSE\", \"host_name\": \"$HOSTNAME\"}" "$CLN_REGISTER_SERVER")
CLN_CODE=$(head -n1 <<< "$CLN_REGISTER")

if [[ ! "$CLN_CODE" == *"200"* ]]; then
    echo "Got incorrect status from CLN: $CLN_REGISTER"
    exit 1
fi

TOKEN=$(echo "$CLN_REGISTER" | grep -oP '"token":"\K[\w\d-]*')

if [[ -z $TOKEN ]]; then
    echo "Something went wrong. Token is not defined"
    exit 1
fi

if ! echo "${TOKEN}" > "$AUTH_CONF_PATH"; then
    echo "Error: Could not write to $AUTH_CONF_PATH"
    exit 10
fi

if ! install_els_os_release; then
    exit 14
fi

yum clean all
if ! yum install -y els-define --disablerepo=* --enablerepo=centos8stream-els; then
    echo "Error: Couldn't install els-define"
    exit 1
fi

echo "CentOS 8 Stream ELS installed successfully"
