#!/usr/bin/env bash
#
# aven installation script
# Usage: curl -fsSL https://raw.githubusercontent.com/raine/aven/main/scripts/install | bash
#
# Environment variables:
#   AVEN_VERSION      - Pin a specific version, such as v0.1.0
#   AVEN_INSTALL_DIR  - Override install directory
#
# Examples:
#   AVEN_VERSION=v0.1.0 bash scripts/install
#   AVEN_INSTALL_DIR=/opt/bin bash scripts/install

set -euo pipefail

readonly red='\033[0;31m'
readonly green='\033[0;32m'
readonly yellow='\033[1;33m'
readonly blue='\033[0;34m'
readonly reset='\033[0m'

install_dir_result=""
tmp_dir_to_remove=""

cleanup() {
    if [[ -n "$tmp_dir_to_remove" ]]; then
        rm -rf "$tmp_dir_to_remove"
    fi
}

log_info() {
    printf '%b==>%b %s\n' "$blue" "$reset" "$1"
}

log_success() {
    printf '%b==>%b %s\n' "$green" "$reset" "$1"
}

log_warning() {
    printf '%b==>%b %s\n' "$yellow" "$reset" "$1"
}

log_error() {
    printf '%bError:%b %s\n' "$red" "$reset" "$1" >&2
}

fetch_url() {
    local url=$1
    local output=$2

    if command -v curl >/dev/null 2>&1; then
        curl -fsSL --retry 3 --retry-connrefused --connect-timeout 10 --max-time 120 -o "$output" "$url"
    elif command -v wget >/dev/null 2>&1; then
        wget --tries=3 --timeout=120 -q -O "$output" "$url"
    else
        log_error "Neither curl nor wget found. Please install one of them."
        exit 1
    fi
}

fetch_stdout() {
    local url=$1

    if command -v curl >/dev/null 2>&1; then
        curl -fsSL --retry 3 --retry-connrefused --connect-timeout 10 --max-time 30 "$url"
    elif command -v wget >/dev/null 2>&1; then
        wget --tries=3 --timeout=30 -qO- "$url"
    else
        log_error "Neither curl nor wget found. Please install one of them."
        exit 1
    fi
}

detect_platform() {
    local os
    local arch

    case "$(uname -s)" in
        Darwin)
            os="darwin"
            ;;
        Linux)
            os="linux"
            ;;
        *)
            log_error "Unsupported operating system: $(uname -s)"
            printf '\naven supports macOS and Linux.\n'
            printf 'For other platforms, try building from source with Cargo:\n'
            printf '  cargo install --git https://github.com/raine/aven\n\n'
            exit 1
            ;;
    esac

    case "$(uname -m)" in
        x86_64 | amd64)
            arch="amd64"
            ;;
        aarch64 | arm64)
            arch="arm64"
            ;;
        *)
            log_error "Unsupported architecture: $(uname -m)"
            printf '\naven release binaries are available for amd64 and arm64.\n'
            printf 'For other architectures, try building from source with Cargo:\n'
            printf '  cargo install --git https://github.com/raine/aven\n\n'
            exit 1
            ;;
    esac

    printf '%s-%s\n' "$os" "$arch"
}

latest_version() {
    local latest_url="https://api.github.com/repos/raine/aven/releases/latest"
    local release_json

    log_info "Fetching latest release..." >&2
    release_json=$(fetch_stdout "$latest_url")
    printf '%s\n' "$release_json" | sed -n -E 's/.*"tag_name": "([^"]+)".*/\1/p'
}

verify_checksum() {
    local checksum_file=$1

    if command -v sha256sum >/dev/null 2>&1; then
        sha256sum -c "$checksum_file" >/dev/null
    elif command -v shasum >/dev/null 2>&1; then
        shasum -a 256 -c "$checksum_file" >/dev/null
    else
        log_warning "Neither sha256sum nor shasum found, skipping checksum verification"
        return 0
    fi
}

default_install_dir() {
    if [[ -w /usr/local/bin ]]; then
        printf '/usr/local/bin\n'
    else
        printf '%s/.local/bin\n' "$HOME"
    fi
}

install_binary() {
    local source_binary=$1
    local install_dir=$2
    local target_binary="$install_dir/aven"
    local tmp_binary="$install_dir/aven.tmp.$$"

    mkdir -p "$install_dir"
    log_info "Installing to $target_binary..."

    if [[ -w "$install_dir" ]]; then
        cp "$source_binary" "$tmp_binary"
        chmod 0755 "$tmp_binary"
        mv -f "$tmp_binary" "$target_binary"
    else
        if ! command -v sudo >/dev/null 2>&1; then
            log_error "$install_dir is not writable and sudo is not available"
            exit 1
        fi
        sudo cp "$source_binary" "$tmp_binary"
        sudo chmod 0755 "$tmp_binary"
        sudo mv -f "$tmp_binary" "$target_binary"
    fi

    if [[ "$(uname -s)" == "Darwin" ]] && command -v xattr >/dev/null 2>&1; then
        xattr -d com.apple.quarantine "$target_binary" 2>/dev/null || true
    fi
}

install_from_release() {
    local platform=$1
    local version=${AVEN_VERSION:-}
    local install_dir=${AVEN_INSTALL_DIR:-}
    local tmp_dir
    local archive_name
    local checksum_file
    local download_url
    local checksum_url

    tmp_dir=$(mktemp -d)
    tmp_dir_to_remove=$tmp_dir
    trap cleanup EXIT

    if [[ -z "$version" ]]; then
        version=$(latest_version)
        if [[ -z "$version" ]]; then
            log_error "Failed to fetch latest version"
            printf '\nSpecify a version manually:\n'
            printf '  AVEN_VERSION=v0.1.0 bash scripts/install\n\n'
            exit 1
        fi
    fi

    archive_name="aven-${platform}.tar.gz"
    checksum_file="${archive_name%.tar.gz}.sha256"
    download_url="https://github.com/raine/aven/releases/download/${version}/${archive_name}"
    checksum_url="https://github.com/raine/aven/releases/download/${version}/${checksum_file}"

    log_info "Installing version: $version"
    log_info "Downloading $archive_name..."
    fetch_url "$download_url" "$tmp_dir/$archive_name"

    log_info "Verifying checksum..."
    fetch_url "$checksum_url" "$tmp_dir/$checksum_file"
    (cd "$tmp_dir" && verify_checksum "$checksum_file")
    log_success "Checksum verified"

    log_info "Extracting archive..."
    tar -xzf "$tmp_dir/$archive_name" -C "$tmp_dir"

    if [[ -z "$install_dir" ]]; then
        install_dir=$(default_install_dir)
    fi

    install_binary "$tmp_dir/aven" "$install_dir"
    install_dir_result=$install_dir
}

verify_installation() {
    local install_dir=$1
    local binary="$install_dir/aven"

    if [[ ! -x "$binary" ]]; then
        log_error "aven binary not found or not executable at $binary"
        exit 1
    fi

    if ! "$binary" --help >/dev/null 2>&1; then
        log_error "aven binary exists but failed to run"
        exit 1
    fi

    log_success "aven is installed and ready!"
    printf '\nGet started:\n'
    printf '  aven config init\n'
    printf '  aven tui\n\n'
    printf 'Documentation: https://github.com/raine/aven\n\n'

    if [[ ":$PATH:" != *":$install_dir:"* ]]; then
        log_warning "$install_dir is not in your PATH"
        printf '\nAdd this to your shell profile:\n'
        printf "  export PATH=\"\$PATH:%s\"\n\n" "$install_dir"
    fi
}

main() {
    local platform

    printf '\naven installer\n\n'
    log_info "Detecting platform..."
    platform=$(detect_platform)
    log_info "Platform: $platform"

    install_from_release "$platform"
    verify_installation "$install_dir_result"
}

main "$@"
