#!/bin/bash

DISABLE_AGENT_UP=${DISABLE_AGENT_UP:-0}

set -euo pipefail

QLAD_TERRAFORM_VERSION="${QLAD_TERRAFORM_VERSION:-latest}"
QLADCTL_VERSION="${QLADCTL_VERSION:-latest}"
AGENT_INSTALL_VERSION="${AGENT_INSTALL_VERSION:-latest}"

readonly DEFAULT_WORKDIR="/tmp/qlad-workdir"
WORKDIR="${WORKDIR:-${DEFAULT_WORKDIR}}"

AZURE_RESOURCE_GROUP="${AZURE_RESOURCE_GROUP:-}"

info() {
    echo "$*"
}

error() {
    echo "Error: $*" >&2
}

error_no_prefix() {
    echo "$*" >&2
}

fatal() {
    echo "Fatal error: $*" >&2

    exit 1
}

check_deps() {
    local deps="kustomize kubectl curl tar bzip2 sipcalc jq"
    local missing_deps=""

    echo -n "    Checking installation dependencies... "

    for dep in ${deps}; do
        command -v "${dep}" &> /dev/null || missing_deps+=" ${dep}"
    done

    # Explicitly check for terraform or tofu
    command -v terraform &> /dev/null || {
        command -v tofu &> /dev/null || {
            missing_deps+=" [terraform|tofu]"
        }
    }

    [[ -z ${missing_deps} ]] || {
        missing_deps="${missing_deps#"${missing_deps%%[![:space:]]*}"}"

        echo "failed"

        error "The following dependencies are not found: ${missing_deps}"

        return 1
    }

    echo "ok"
}

detect_target_cluster_provider() {
    echo -n "    Detecting target cluster environment... "

    # Test Kubernetes environment
    PROVIDERRAW=$(kubectl get nodes --output json 2> /dev/null | jq -r '.items[].spec.providerID') || {
        echo "failed"

        fatal "unable to determine target cluster environment (\"kubectl get nodes\" failed)"
    }

    [[ -z ${PROVIDERRAW} ]] && fatal "unable to detect target cluster environment"

    case "${PROVIDERRAW%%:*}" in
        aws|azure)
            PROVIDER="${PROVIDERRAW%%:*}"
            ;;
        gce)
            PROVIDER=gcp
            ;;
        *)
            PROVIDER="local"
            ;;
    esac

    echo "${PROVIDER}"
}

detect_host_environment() {
    case $(uname) in
        Linux)
            PLATFORM=linux
            ;;
        Darwin)
            PLATFORM=macos
            ;;
        *)
            fatal "platform $(uname) is not supported"
            ;;
    esac

    case $(uname -m) in
        x86_64)
            ARCH=x86_64
            ;;
        arm64)
            ARCH=arm64
            ;;
        *)
            error "architecture $(uname -m) is not supported" >&2 && exit 1
            ;;
    esac

    echo "    Detected host environment... ${PLATFORM}/${ARCH}"
}

get_file() {
    local url
    local dstfile=""

    url="${1}"

    [[ $# -gt 1 ]] && dstfile="${2}"

    local curlcmd="curl --fail --silent"

    if [[ -n ${dstfile} ]]; then
        curlcmd+=" --output \"${dstfile}\""
    else
        curlcmd+=" --remote-name"
    fi

    curlcmd+=" ${url}"

    eval "${curlcmd}"
}

validate_checksum() {
    get_file "${1}" - | sha256sum --ignore-missing --check - &> /dev/null
}

check_prereqs() {
    if [[ ${PROVIDER} == aws ]]; then
        kubectl get secret qlad-config-secret &> /dev/null || {
            error_no_prefix ""
            error "ensure the secret 'qlad-config-secret' exists prior to installing QLAD in AWS/EKS."
            error_no_prefix ""
            error_no_prefix "This secret must contain key/value pairs for AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY."

            exit 1
        }
    fi
}

main() {
    [[ $# -eq 1 ]] || {
        error "Missing INSTALL_ID argument.

usage: $(basename "${0}") INSTALL_ID"

        exit 0
    }

    echo "Bootstrapping QLAD Agent..."

    # Check local dependencies
    check_deps || exit 1

    # Detect target cluster provider (ie. azure, aws, local)
    detect_target_cluster_provider

    # Detect host environment (Linux or macOS)
    detect_host_environment

    # Check for installation prerequisites
    check_prereqs

    local QLAD_TERRAFORM_TARBALL="qlad-terraform-${QLAD_TERRAFORM_VERSION}.tar.bz2"
    local QLADCTL_TARBALL="qladctl-${QLADCTL_VERSION}-${PLATFORM}-${ARCH}.tar.bz2"
    local AGENT_INSTALL_TARBALL="qlad-agent-${AGENT_INSTALL_VERSION}.tar.bz2"

    # Create temporary work directory
    mkdir -p "${WORKDIR}/install"

    pushd "${WORKDIR}" &> /dev/null || fatal "changing to ${WORKDIR}"

    # Get Terraform configuration
    get_file "https://get.qlad.com/qlad-terraform/${QLAD_TERRAFORM_VERSION}/${QLAD_TERRAFORM_TARBALL}" || fatal "fetching Terraform configuration"

    validate_checksum "https://get.qlad.com/qlad-terraform/${QLAD_TERRAFORM_VERSION}/qlad-terraform-checksums.txt" || {
        fatal "checksum error on Terraform configuration tarball"
    }

    tar jxf ${QLAD_TERRAFORM_TARBALL} || fatal "extracting Terraform configuration tarball"

    # Get qladctl for host platform
    get_file "https://get.qlad.com/qladctl/${QLADCTL_VERSION}/${QLADCTL_TARBALL}" || fatal "fetching qladctl"

    validate_checksum "https://get.qlad.com/qladctl/${QLADCTL_VERSION}/qladctl-${PLATFORM}-${ARCH}-checksums.txt" || {
        fatal "checksum error on qladctl tarball"
    }

    mkdir -p qladctl

    # Extract qladctl tarball
    tar --extract --bzip2 --file "${QLADCTL_TARBALL}" --strip-components 1 --directory qladctl || {
        fatal "extracting qladctl tarball"
    }

    # Get Kustomize configuration for installing QLAD Agent
    get_file "https://get.qlad.com/qlad-agent/${AGENT_INSTALL_VERSION}/${AGENT_INSTALL_TARBALL}" || {
        fatal "fetching Kubernetes configuration tarball"
    }

    validate_checksum "https://get.qlad.com/qlad-agent/${AGENT_INSTALL_VERSION}/qlad-agent-checksums.txt" || fatal "checksum error on Kubernetes configuration tarball"

    tar --extract --bzip2 --file "${AGENT_INSTALL_TARBALL}" || fatal "Error extracting qladctl tarball"

    get_file "https://get.qlad.dev/root-ca.pem" || fatal "getting Root CA certificate"

    popd &> /dev/null || fatal "changing directory"

    local agent_up_cmdline="${WORKDIR}/qladctl/bin/qladctl agent up \
--provider ${PROVIDER} \
--domain qlad.dev"

    [[ ${DISABLE_AGENT_UP} -eq 1 ]] && {
        echo "Skipping \"qladctl agent up\"... (DISABLE_AGENT_UP=1)"
        echo
        echo "Run following command to complete installation:"
        echo

        output=""
        [[ -n ${AZURE_RESOURCE_GROUP} ]] && output+="AZURE_RESOURCE_GROUP=${AZURE_RESOURCE_GROUP} "
        [[ -n ${WORKDIR} ]] && [[ "${DEFAULT_WORKDIR}" != "${WORKDIR}" ]] && output+="WORKDIR=\"${WORKDIR}\" "

        output+="${agent_up_cmdline}"
        output+=" $@"

        echo "${output}"

        return 0
    }

    echo
    echo "Starting QLAD Agent installation..."

    ${agent_up_cmdline} "$@"
}

main "$@"
