#!/usr/bin/env bash
# RepoQL installer for macOS and Linux.
# Downloads the rql binary, places it in ~/.local/bin, adds that to PATH,
# and runs `rql install` to finish setup.

set -euo pipefail

main() {
    printf '\n╭─────────────────────────────────────╮\n'
    printf   '│   Installing RepoQL (rql)           │\n'
    printf   '╰─────────────────────────────────────╯\n\n'

    stop_running_rql

    local install_dir="${HOME}/.local/bin"
    local binary_name="rql"
    local platform
    platform=$(detect_platform) || exit 1

    echo "Detected platform: $platform"

    mkdir -p "$install_dir"

    local download_url
    if [[ "$platform" == win-* ]]; then
        download_url="https://downloads.repoql.ai/latest/${platform}/rql.exe"
        binary_name="rql.exe"
    else
        download_url="https://downloads.repoql.ai/latest/${platform}/rql"
    fi

    local dest_path="${install_dir}/${binary_name}"
    local tmp_path="${dest_path}.download.$$"

    echo "Downloading from: $download_url"
    # Download to a sibling temp file first, then atomically move into place.
    # An interrupted download must not leave a half-written binary.
    trap 'rm -f "$tmp_path" 2>/dev/null || true' EXIT
    if ! curl -fSL --progress-bar "$download_url" -o "$tmp_path"; then
        echo "Download failed. Check your connection and that $download_url is reachable." >&2
        exit 1
    fi

    if [[ "$platform" != win-* ]]; then
        chmod +x "$tmp_path"
    fi

    mv -f "$tmp_path" "$dest_path"
    trap - EXIT

    create_repoql_alias "$install_dir" "$binary_name"

    ensure_on_path "$install_dir"

    echo
    echo "rql installed at: $dest_path"
    echo

    if [ -t 0 ]; then
        echo "Running 'rql install'..."
        "$dest_path" install
        echo
        echo "Done."
    else
        echo "To complete setup, run:"
        echo
        echo "  export PATH=\"\$PATH:$install_dir\" && rql install"
    fi
}

detect_platform() {
    local os arch
    os=$(uname -s | tr '[:upper:]' '[:lower:]')
    arch=$(uname -m)

    case "$os" in
        darwin)
            case "$arch" in
                arm64)
                    echo "osx-arm64"
                    ;;
                x86_64)
                    echo "osx-x64"
                    ;;
                *)
                    echo "Unsupported macOS architecture: $arch." >&2
                    echo "RepoQL ships for Apple Silicon (arm64) and Intel (x86_64) macs." >&2
                    return 1
                    ;;
            esac
            ;;
        linux)
            case "$arch" in
                x86_64|amd64)
                    echo "linux-x64"
                    ;;
                aarch64|arm64)
                    echo "linux-arm64"
                    ;;
                *)
                    echo "Unsupported Linux architecture: $arch." >&2
                    echo "RepoQL ships for x86_64 and aarch64 only." >&2
                    return 1
                    ;;
            esac
            ;;
        mingw*|msys*|cygwin*)
            case "$arch" in
                x86_64|amd64)
                    echo "win-x64"
                    ;;
                aarch64|arm64)
                    echo "win-arm64"
                    ;;
                *)
                    echo "Unsupported Windows architecture: $arch." >&2
                    echo "RepoQL ships for x86_64 and aarch64 only." >&2
                    return 1
                    ;;
            esac
            ;;
        *)
            echo "Unsupported OS: $os" >&2
            return 1
            ;;
    esac
}

stop_running_rql() {
    # Gentle first — SIGTERM gives a chance to flush state. Then force after a moment.
    # -x matches the exact process name so we don't catch 'rql-anything' by accident.
    if pkill -x rql 2>/dev/null; then
        echo "Stopping running rql instance..."
        sleep 1
        pkill -9 -x rql 2>/dev/null || true
    fi
}

create_repoql_alias() {
    local install_dir="$1"
    local binary_name="$2"
    local alias_name
    if [[ "$binary_name" == *.exe ]]; then
        alias_name="repoql.exe"
    else
        alias_name="repoql"
    fi
    local alias_path="${install_dir}/${alias_name}"

    ln -sfn "$binary_name" "$alias_path"
}

ensure_on_path() {
    local install_dir="$1"
    if [[ ":$PATH:" == *":$install_dir:"* ]]; then
        return
    fi

    local shell_name rc_file
    shell_name=$(basename "${SHELL:-}")
    case "$shell_name" in
        zsh)
            rc_file="$HOME/.zshrc"
            ;;
        bash)
            if [[ -f "$HOME/.bash_profile" ]]; then
                rc_file="$HOME/.bash_profile"
            else
                rc_file="$HOME/.bashrc"
            fi
            ;;
        *)
            rc_file="$HOME/.profile"
            ;;
    esac

    # Fixed-string search — catches any existing line that mentions install_dir
    # regardless of quoting, path+= style, or two-line export form.
    if grep -qF "$install_dir" "$rc_file" 2>/dev/null; then
        export PATH="$PATH:$install_dir"
        return
    fi

    echo "Adding $install_dir to PATH (via $rc_file)..."

    # Ensure the rc file ends with a newline before appending; otherwise our
    # new block would start on the same line as an existing statement.
    if [[ -s "$rc_file" && -n "$(tail -c1 "$rc_file")" ]]; then
        echo >> "$rc_file"
    fi

    {
        echo "# Added by RepoQL installer"
        echo "export PATH=\"\$PATH:$install_dir\""
    } >> "$rc_file"

    export PATH="$PATH:$install_dir"
}

main "$@"
