#!/usr/bin/env bash

# install-desktop - Automatically install MUSACODE Desktop client
# Supports macOS, Windows, Linux multiple architectures
# Usage: curl -fsSL https://example.com/install-desktop | bash
# Or: curl -fsSL https://example.com/install-desktop | bash -s -- --version 1.0.0.rc.1

set -euo pipefail

# ==============================================================================
# Configuration
# ==============================================================================
VERSION="latest"
TOS_BUCKET="musacode.tos-cn-beijing.volces.com"

# Human-readable platform descriptions (display only)
declare -A PLATFORM_DESC=(
    # ["darwin-arm64"]="macOS (Apple Silicon)"
    # ["darwin-x86_64"]="macOS (Intel)"
    ["windows-x64-exe"]="Windows (x64)"
    ["linux-x64-deb"]="Linux amd64 (.deb)"
    ["linux-x64-rpm"]="Linux x86_64 (.rpm)"
    ["linux-arm64-rpm"]="Linux aarch64 (.rpm)"
    ["linux-arm64-deb"]="Linux arm64 (.deb)"
)

# Windows package priority (higher = tried first)
declare -a WINDOWS_PACKAGE_PRIORITY=(
    "windows-x64-electron"
    "windows-x64-tauri"
)

# ==============================================================================
# Utility Functions
# ==============================================================================

# Print help text
show_help() {
    cat << EOF
MUSACODE Desktop Installation Script

Usage:
  curl -fsSL https://example.com/install-desktop | bash
  curl -fsSL https://example.com/install-desktop | bash -s -- --version <version>
  curl -fsSL https://example.com/install-desktop | bash -s -- --help

Parameters:
  --version <version>  Specify installation version (default: latest)
  --help               Show this help message

Examples:
  # Install the latest version
  curl -fsSL https://example.com/install-desktop | bash
  
  # Install a specific version
  curl -fsSL https://example.com/install-desktop | bash -s -- --version 1.0.0.rc.1
EOF
}

# Download a single file with optional progress bar
download_file() {
    local url="$1"
    local output="$2"
    local quiet="${3:-false}"

    if command -v curl &> /dev/null; then
        if [[ "$quiet" == "false" ]]; then
            echo "Downloading: $url"
            # --progress-bar shows a nice interactive progress bar (stderr)
            curl -fL --progress-bar "$url" -o "$output"
        else
            curl -sfL "$url" -o "$output"
        fi
        return $?
    elif command -v wget &> /dev/null; then
        if [[ "$quiet" == "false" ]]; then
            echo "Downloading: $url"
            wget --progress=bar:force "$url" -O "$output"
        else
            wget -q "$url" -O "$output"
        fi
        return $?
    else
        echo "Error: Neither curl nor wget is available. Please install one of them."
        return 1
    fi
}

# Get Windows desktop path, fallback to current directory
get_windows_desktop_path() {
    local desktop_path=""

    if [[ -n "$USERPROFILE" ]]; then
        desktop_path="$USERPROFILE/Desktop"
    elif [[ -n "$HOME" ]]; then
        desktop_path="$HOME/Desktop"
    elif command -v powershell &> /dev/null; then
        desktop_path=$(powershell -Command "[Environment]::GetFolderPath('Desktop')" 2>/dev/null | tr -d '\r\n')
    fi

    if [[ -z "$desktop_path" ]] || [[ ! -d "$desktop_path" ]]; then
        echo "Warning: Desktop directory not found. Using current directory instead."
        desktop_path="."
    fi

    echo "$desktop_path"
}

# Clean up temporary directory (used on non-Windows)
cleanup_temp_dir() {
    local temp_dir="$1"
    [[ -d "$temp_dir" ]] && rm -rf "$temp_dir"
}

# Generate the exact package filename for a given Windows variant
generate_win_filename() {
    local variant="$1"
    local ver="$2"
    case "$variant" in
        windows-x64-electron) echo "musacode-electron-win-x64-${ver}.exe" ;;
        windows-x64-tauri)    echo "MUSACODE_x64-setup-${ver}.exe" ;;
        *)                  echo "" ;;
    esac
}

# ==============================================================================
# Core Steps
# ==============================================================================

# Step 1: Parse command line arguments
parse_args() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            --version)
                if [[ -n "${2:-}" ]]; then
                    VERSION="$2"
                    shift 2
                else
                    echo "Error: --version requires a value."
                    exit 1
                fi
                ;;
            --help)
                show_help
                exit 0
                ;;
            *)
                echo "Error: Unknown option: $1"
                show_help
                exit 1
                ;;
        esac
    done
}

# Step 2: Detect OS, architecture and package manager
detect_platform() {
    local os_name="" arch="" pkg_manager=""

    case "$(uname -s)" in
        Linux*)   os_name="linux" ;;
        Darwin*)  os_name="darwin" ;;
        MINGW*|MSYS*|CYGWIN*) os_name="windows" ; pkg_manager="exe" ;;
        *)
            echo "Error: Unsupported operating system: $(uname -s)"
            exit 1
            ;;
    esac

    case "$(uname -m)" in
        x86_64|amd64)     arch="x64" ;;
        aarch64|arm64)    arch="arm64" ;;
        armv7l|armv8l)    arch="arm" ;;
        *)
            echo "Error: Unsupported architecture: $(uname -m)"
            exit 1
            ;;
    esac

    if [[ "$os_name" == "linux" ]]; then
        if command -v apt-get &> /dev/null; then
            pkg_manager="deb"
        elif command -v yum &> /dev/null || command -v dnf &> /dev/null; then
            pkg_manager="rpm"
        else
            echo "Error: No supported package manager found (apt, yum, dnf)."
            exit 1
        fi
    fi

    PLATFORM="${os_name}-${arch}-${pkg_manager}"
}

# Step 3: Resolve actual version (if "latest", fetch from server)
resolve_version() {
    [[ "$VERSION" != "latest" ]] && return

    local fetched
    fetched=$(curl -sfL "https://${TOS_BUCKET}/desktop/latest" | tr -d '[:space:]')
    if [[ -z "$fetched" ]]; then
        echo "Error: Failed to fetch latest version from server."
        exit 1
    fi
    VERSION="${fetched#v}"   # strip leading 'v'
}

# Step 4: Determine the package name for non-Windows platforms.
#         Windows package selection is deferred to the download step.
select_package_name() {
    os_arch=$(echo ${PLATFORM} | cut -d'-' -f1-2)  # e.g. linux-x64
    PACKAGE_NAME=""
    if [[ "$PLATFORM" == "windows-x64-exe" ]]; then
        for variant in "${WINDOWS_PACKAGE_PRIORITY[@]}"; do
            local pkg_name
            pkg_name=$(generate_win_filename "$variant" "$VERSION")
            [[ -z "$pkg_name" ]] && continue

            local url="https://${TOS_BUCKET}/desktop/v${VERSION}/${os_arch}/${pkg_name}"

            echo "Checking availability of Windows package: $pkg_name"
            echo "URL: $url"

            status=$(curl -I ${url} -s -o /dev/null -w "%{http_code}")
            if [[ "$status" -eq 200 ]]; then
                PACKAGE_NAME="$pkg_name"
                break
            fi
        done
        return
    fi

    case "$PLATFORM" in
        linux-x64-deb)   PACKAGE_NAME="musacode-electron-linux-amd64-${VERSION}.deb" ;;
        linux-x64-rpm)   PACKAGE_NAME="musacode-electron-linux-x86_64-${VERSION}.rpm" ;;
        linux-arm64-deb)   PACKAGE_NAME="musacode-electron-linux-arm64-${VERSION}.deb" ;;
        linux-arm64-rpm)   PACKAGE_NAME="musacode-electron-linux-aarch64-${VERSION}.rpm" ;;
        darwin-arm64|darwin-x86_64) PACKAGE_NAME="MUSACODE Desktop.dmg" ;;
        *)
            echo "Error: Unsupported platform: $PLATFORM"
            echo "Supported platforms:"
            for key in "${!PLATFORM_DESC[@]}"; do
                echo "  - ${PLATFORM_DESC[$key]}"
            done
            exit 1
            ;;
    esac
}

# Step 5: Download the installer
perform_download() {
    os_arch=$(echo ${PLATFORM} | cut -d'-' -f1-2)  # e.g. linux-x64
    if [[ "$PLATFORM" == "windows-x64-exe" ]]; then
        local desktop_dir
        desktop_dir=$(get_windows_desktop_path)
        local downloaded=false

        [[ -z "$PACKAGE_NAME" ]] && continue

        local url="https://${TOS_BUCKET}/desktop/v${VERSION}/${os_arch}/${PACKAGE_NAME}"
        local output="${desktop_dir}/${PACKAGE_NAME}"

        if download_file "$url" "$output" false; then
            echo "Successfully downloaded: $url"
            OUTPUT_FILE="$output"
            downloaded=true
        fi

        if [[ "$downloaded" == false ]]; then
            echo "Error: Windows desktop failed to download."
            exit 1
        fi
    else
        TEMP_DIR=$(mktemp -d)
        OUTPUT_FILE="${TEMP_DIR}/${PACKAGE_NAME}"
        trap 'cleanup_temp_dir "$TEMP_DIR"' EXIT

        local url="https://${TOS_BUCKET}/desktop/v${VERSION}/${os_arch}/${PACKAGE_NAME}"
        if ! download_file "$url" "$OUTPUT_FILE"; then
            echo "Error: Failed to download package."
            exit 1
        fi
    fi
}

# Step 6: Install the downloaded package
install_package() {
    local package_file="$1"
    local platform="$2"

    echo "Installing: $package_file"

    case "$platform" in
        darwin*)
            if [[ "$package_file" == *.dmg ]]; then
                echo "Please manually mount and install the DMG file: $package_file"
                echo "Alternatively, use:"
                echo "  hdiutil attach \"$package_file\""
                echo "  # Drag the app to Applications folder"
            fi
            ;;

        win*)
            echo "Installation package saved to: $package_file"
            echo "Please double-click to run the installer."
            ;;

        linux*)
            local target_user="${SUDO_USER:-$USER}"
            if [[ -n "$target_user" ]]; then
                local data_dir="/home/${target_user}/.local/share/musacode"
                if [[ ! -d "$data_dir" ]]; then
                    echo "Creating directory structure: $data_dir"
                    sudo mkdir -p "${data_dir}"/{bin,log,snapshot,storage,tool-output}
                    sudo touch "${data_dir}/musacode.db"
                    sudo chown -R "${target_user}:${target_user}" "$data_dir"
                fi
            fi

            if [[ "$package_file" == *.deb ]]; then
                sudo dpkg --remove musacode 2>/dev/null || true
                sudo dpkg --remove musacode-desktop-electron 2>/dev/null || true
                if command -v sudo &> /dev/null; then
                    sudo dpkg -i "$package_file" || sudo apt-get install -f -y
                else
                    dpkg -i "$package_file" || apt-get install -f -y
                fi
            elif [[ "$package_file" == *.rpm ]]; then
                if command -v sudo &> /dev/null; then
                    if command -v dnf &> /dev/null; then
                        sudo dnf install -y "$package_file"
                    else
                        sudo rpm -i "$package_file" || sudo yum install -y "$package_file"
                    fi
                else
                    rpm -i "$package_file" || yum install -y "$package_file"
                fi
            fi
            ;;
    esac

    echo "Installation completed successfully!"
}

# ==============================================================================
# Main Entry Point
# ==============================================================================
main() {
    # Step 1: Parse arguments
    parse_args "$@"

    # Step 2: Detect platform
    detect_platform

    # Step 3: Resolve version (fetch latest if needed)
    resolve_version

    # Step 4: Determine package name (non-Windows only)
    select_package_name

    # Display summary
    echo ""
    echo "========================================="
    echo " MUSACODE Desktop Installer"
    echo "========================================="
    echo " Version:       $VERSION"
    echo " Platform:      ${PLATFORM_DESC[$PLATFORM]:-$PLATFORM}"
    echo " Package:       ${PACKAGE_NAME:-N/A}"
    echo "========================================="
    echo ""

    # Step 5: Download
    perform_download

    # Step 6: Install
    install_package "$OUTPUT_FILE" "$PLATFORM"
}

main "$@"