#!/usr/bin/env sh
# ==========================================================
#  Poly Studio - macOS & Linux Installer (one-line install)
#  Usage:
#    curl -fsSL https://polystudio.vaapps.com/install.sh | sh
# ==========================================================
set -eu

RED='\033[0;31m'
GREEN='\033[0;32m'
CYAN='\033[0;36m'
YELLOW='\033[1;33m'
GRAY='\033[0;90m'
NC='\033[0m' # No Color

log_step() {
    printf "${CYAN}[Poly Studio]${NC} %s\n" "$1"
}

log_ok() {
    printf "${GREEN}[Poly Studio]${NC} %s\n" "$1"
}

log_warn() {
    printf "${YELLOW}[Poly Studio] WARNING:${NC} %s\n" "$1"
}

die() {
    printf "${RED}[Poly Studio] ERROR:${NC} %s\n" "$1" >&2
    exit 1
}

# Animated spinner for long operations (extraction). Automatically disabled
# when stdout is not a terminal (piped/redirected output) so logs stay clean.
SPIN_CHARS='|/-\'
spin() {
    _spin_pid="$1"; _spin_label="$2"
    i=0
    while kill -0 "$_spin_pid" 2>/dev/null; do
        c="$(printf '%s' "$SPIN_CHARS" | cut -c "$((i % 4 + 1))")"
        printf "\r${CYAN}[Poly Studio]${NC} %s %s  " "$_spin_label" "$c"
        i=$((i + 1))
        sleep 0.2 2>/dev/null || sleep 1
    done
}

run_with_spinner() {
    _rws_label="$1"; shift
    if [ -t 1 ]; then
        "$@" &
        _rws_pid=$!
        spin "$_rws_pid" "$_rws_label"
        if wait "$_rws_pid"; then
            printf "\r\033[K"
            return 0
        fi
        printf "\n"
        return 1
    fi
    "$@"
}

printf "\n"
printf "${CYAN}==========================================================${NC}\n"
printf "${CYAN}          Poly Studio - Cross-Platform Installer          ${NC}\n"
printf "${CYAN}==========================================================${NC}\n\n"

# 1. Check OS and Architecture
OS="$(uname -s)"
ARCH="$(uname -m)"

if [ "$OS" = "Darwin" ]; then
    PLATFORM="macos"
    if [ "$ARCH" = "arm64" ] || [ "$ARCH" = "aarch64" ]; then
        ZIP_NAME="PolyStudio-osx-arm64.zip"
        PLATFORM_DESC="macOS Apple Silicon (M1/M2/M3/M4)"
    elif [ "$ARCH" = "x86_64" ] || [ "$ARCH" = "amd64" ]; then
        ZIP_NAME="PolyStudio-osx-x64.zip"
        PLATFORM_DESC="macOS Intel (x86_64)"
    else
        die "Poly Studio for macOS supports Apple Silicon (arm64) and Intel (x86_64). Detected unsupported arch: $ARCH"
    fi
elif [ "$OS" = "Linux" ]; then
    PLATFORM="linux"
    if [ "$ARCH" = "x86_64" ] || [ "$ARCH" = "amd64" ]; then
        ZIP_NAME="PolyStudio-linux-x64.zip"
        PLATFORM_DESC="Linux (x86_64)"
    elif [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then
        ZIP_NAME="PolyStudio-linux-arm64.zip"
        PLATFORM_DESC="Linux (ARM64)"
    else
        die "Poly Studio Linux native build requires x86_64/amd64 or aarch64/arm64 architecture. Detected unsupported arch: $ARCH"
    fi
else
    die "This installer is for macOS or Linux. Detected OS: $OS. For Windows, run: irm https://polystudio.vaapps.com/install.ps1 | iex"
fi

log_step "Detected platform: $PLATFORM_DESC"

# 2. Determine target directories
if [ "$PLATFORM" = "macos" ]; then
    INSTALL_DIR="${HOME}/.local/share/polystudio"
    BIN_DIR="/usr/local/bin"
    # If /usr/local/bin is not writable without sudo, fall back to ~/.local/bin
    if [ ! -w "$BIN_DIR" ] && [ "$(id -u)" -ne 0 ]; then
        BIN_DIR="${HOME}/.local/bin"
    fi
else
    if [ "$(id -u)" -eq 0 ]; then
        INSTALL_DIR="/opt/polystudio"
        BIN_DIR="/usr/local/bin"
    else
        INSTALL_DIR="${HOME}/.local/share/polystudio"
        BIN_DIR="${HOME}/.local/bin"
    fi
fi

BASE_URL="${POLYSTUDIO_DOWNLOAD_URL:-https://polystudio.vaapps.com}"
BASE_URL="${BASE_URL%/}"
CACHE_BUSTER="$(date +%s 2>/dev/null || echo $$)"
# Zips are served under /downloads/ (site root no longer serves them)
ZIP_URL="${BASE_URL}/downloads/${ZIP_NAME}?t=${CACHE_BUSTER}"
TEMP_ZIP="/tmp/polystudio-${PLATFORM}-$$.zip"

# 3. Check for download tool
if command -v curl >/dev/null 2>&1; then
    DOWNLOAD_CMD="curl -fsSL"
elif command -v wget >/dev/null 2>&1; then
    DOWNLOAD_CMD="wget -qO"
else
    die "Neither 'curl' nor 'wget' was found on your system. Please install one of them and retry."
fi

# 4. Check for unzip tool
HAS_UNZIP=false
if command -v unzip >/dev/null 2>&1; then
    HAS_UNZIP=true
elif command -v python3 >/dev/null 2>&1; then
    HAS_UNZIP=false
else
    die "Missing unzip utility. Please install 'unzip' or python3."
fi

# 5. Download package (with progress bar)
if [ -t 1 ]; then
    log_step "Downloading Poly Studio..."
else
    log_step "Downloading Poly Studio from $ZIP_URL..."
fi
if command -v curl >/dev/null 2>&1; then
    if [ -t 1 ]; then
        # Native progress bar: % downloaded, transfer speed, ETA
        curl -#fL "$ZIP_URL" -o "$TEMP_ZIP" || die "Failed to download $ZIP_URL"
    else
        curl -fsSL "$ZIP_URL" -o "$TEMP_ZIP" || die "Failed to download $ZIP_URL"
    fi
elif command -v wget >/dev/null 2>&1; then
    if [ -t 1 ]; then
        wget -q --show-progress --progress=bar:force:noscroll -O "$TEMP_ZIP" "$ZIP_URL" \
            || die "Failed to download $ZIP_URL"
    else
        wget -qO "$TEMP_ZIP" "$ZIP_URL" || die "Failed to download $ZIP_URL"
    fi
fi

if [ ! -s "$TEMP_ZIP" ]; then
    die "Downloaded package is empty or invalid."
fi

if [ -t 1 ]; then
    SIZE_MB=$(du -m "$TEMP_ZIP" 2>/dev/null | cut -f1 || echo "?")
    log_ok "Downloaded ${SIZE_MB} MB."
fi

# 6. Extract into destination
mkdir -p "$INSTALL_DIR"
mkdir -p "$BIN_DIR"

# Stop any running process if in user space
pkill -f "$INSTALL_DIR/PolyStudio" >/dev/null 2>&1 || true

if [ "$HAS_UNZIP" = true ]; then
    run_with_spinner "Extracting package..." unzip -q -o "$TEMP_ZIP" -d "$INSTALL_DIR" \
        || die "Failed to extract the package. The download may be corrupted - please retry."
else
    run_with_spinner "Extracting package..." python3 -c "import zipfile; zipfile.ZipFile('$TEMP_ZIP').extractall('$INSTALL_DIR')" \
        || die "Failed to extract the package. The download may be corrupted - please retry."
fi
if [ -t 1 ]; then
    printf "${GREEN}[Poly Studio]${NC} Extracted successfully.\n"
fi
rm -f "$TEMP_ZIP"

chmod +x "$INSTALL_DIR/PolyStudio"
# Legacy exe-side app.db is intentionally KEPT: the app migrates it into the
# data root (~/.local/share/PolyStudio on Linux, ~/Library/Application
# Support/PolyStudio on macOS) on first run and removes the exe-side copy
# itself. Deleting it here would defeat that migration and lose all user data.

# Clear macOS quarantine attribute if downloaded via web/curl
if [ "$PLATFORM" = "macos" ] && command -v xattr >/dev/null 2>&1; then
    xattr -d com.apple.quarantine "$INSTALL_DIR/PolyStudio" 2>/dev/null || true
fi

# 7. Symlink to BIN_DIR
ln -sf "$INSTALL_DIR/PolyStudio" "$BIN_DIR/polystudio"

# 8. Desktop integration (shortcuts + icons)
#    - Linux: .desktop menu entry + Desktop shortcut icon (when a Desktop dir exists)
#    - macOS: ~/Applications/Poly Studio.app bundle (Launchpad, Spotlight, Dock)
if [ "$PLATFORM" = "linux" ]; then
    DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
    DESKTOP_DIR="$DATA_HOME/applications"
    ICON_DIR="$DATA_HOME/icons/hicolor/scalable/apps"
    PNG_ICON_DIR="$DATA_HOME/icons/hicolor/512x512/apps"

    mkdir -p "$DESKTOP_DIR" "$ICON_DIR" "$PNG_ICON_DIR" 2>/dev/null || true

    # Icons: prefer the SVG shipped next to the binary; fall back to the PNG
    # (both are embedded in the app itself if the loose copy is absent).
    if [ -f "$INSTALL_DIR/polystudio.svg" ]; then
        cp -f "$INSTALL_DIR/polystudio.svg" "$ICON_DIR/polystudio.svg" 2>/dev/null || true
    fi
    if [ -f "$INSTALL_DIR/polystudio.png" ]; then
        cp -f "$INSTALL_DIR/polystudio.png" "$PNG_ICON_DIR/polystudio.png" 2>/dev/null || true
    fi

    cat <<EOF > "$DESKTOP_DIR/polystudio.desktop" 2>/dev/null || true
[Desktop Entry]
Type=Application
Name=Poly Studio
Comment=AI Database Workbench
Exec=$BIN_DIR/polystudio
Icon=polystudio
Terminal=false
Categories=Development;Database;
StartupWMClass=PolyStudio
EOF
    chmod 644 "$DESKTOP_DIR/polystudio.desktop" 2>/dev/null || true
    update-desktop-database "$DESKTOP_DIR" >/dev/null 2>&1 || true

    # Desktop shortcut: only when an actual Desktop folder exists (GNOME/KDE/XFCE).
    # Skip headless/server installs and macOS-style ~/Desktop-less setups.
    for DESK in "$HOME/Desktop" "$HOME/Desktop_CJK" "$HOME/Bureau" "$HOME/Escritorio"; do
        if [ -d "$DESK" ]; then
            if command -v desktop-file-install >/dev/null 2>&1; then
                desktop-file-install --dir="$DESK" --copy-name-to-generic-name \
                    "$DESKTOP_DIR/polystudio.desktop" >/dev/null 2>&1 \
                    || cp -f "$DESKTOP_DIR/polystudio.desktop" "$DESK/polystudio.desktop" 2>/dev/null || true
            else
                cp -f "$DESKTOP_DIR/polystudio.desktop" "$DESK/polystudio.desktop" 2>/dev/null || true
            fi
            # Some desktops (GNOME >= 3.36) require the "allow launch" bit.
            if command -v gio >/dev/null 2>&1; then
                gio set "$DESK/polystudio.desktop" metadata::trusted true >/dev/null 2>&1 || true
            fi
            chmod +x "$DESK/polystudio.desktop" 2>/dev/null || true
            DESKTOP_SHORTCUT="$DESK/polystudio.desktop"
            break
        fi
    done
fi

if [ "$PLATFORM" = "macos" ]; then
    APP_DIR="$HOME/Applications"
    APP_BUNDLE="$APP_DIR/Poly Studio.app"
    CONTENTS="$APP_BUNDLE/Contents/MacOS"
    RESOURCES="$APP_BUNDLE/Contents/Resources"

    mkdir -p "$CONTENTS" "$RESOURCES" 2>/dev/null || true

    # App icon: convert the shipped PNG to .icns (sips ships with macOS).
    if [ -f "$INSTALL_DIR/polystudio.png" ] && command -v sips >/dev/null 2>&1; then
        ICONSET_SRC="$APP_DIR/polystudio.iconset"
        mkdir -p "$ICONSET_SRC" 2>/dev/null || true
        for SZ in 16 32 64 128 256 512; do
            sips -z $SZ $SZ "$INSTALL_DIR/polystudio.png" \
                --out "$ICONSET_SRC/icon_${SZ}x${SZ}.png" >/dev/null 2>&1 || true
            DBL=$((SZ * 2))
            sips -z $DBL $DBL "$INSTALL_DIR/polystudio.png" \
                --out "$ICONSET_SRC/icon_${SZ}x${SZ}@2x.png" >/dev/null 2>&1 || true
        done
        if command -v iconutil >/dev/null 2>&1; then
            iconutil -c icns "$ICONSET_SRC" -o "$RESOURCES/polystudio.icns" >/dev/null 2>&1 || true
        fi
        rm -rf "$ICONSET_SRC" 2>/dev/null || true
    fi

    # Wrapper script: launches the real binary; -o keeps stdout clean on double-click.
    cat <<EOF > "$CONTENTS/PolyStudio" 2>/dev/null || true
#!/bin/sh
exec "$INSTALL_DIR/PolyStudio" "\$@"
EOF
    chmod +x "$CONTENTS/PolyStudio" 2>/dev/null || true

    cat <<EOF > "$APP_BUNDLE/Contents/Info.plist" 2>/dev/null || true
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleExecutable</key>            <string>PolyStudio</string>
    <key>CFBundleName</key>                  <string>Poly Studio</string>
    <key>CFBundleDisplayName</key>           <string>Poly Studio</string>
    <key>CFBundleIdentifier</key>            <string>com.vaapps.polystudio</string>
    <key>CFBundlePackageType</key>           <string>APPL</string>
    <key>CFBundleVersion</key>               <string>1.0</string>
    <key>CFBundleShortVersionString</key>    <string>1.0</string>
    <key>CFBundleIconFile</key>              <string>polystudio</string>
    <key>LSMinimumSystemVersion</key>        <string>10.15</string>
    <key>NSHighResolutionCapable</key>       <true/>
    <key>NSSupportsAutomaticGraphicsSwitching</key> <true/>
</dict>
</plist>
EOF

    # Register the app with LaunchServices so Spotlight/Launchpad pick it up.
    if command -v lsregister >/dev/null 2>&1; then
        lsregister -f "$APP_BUNDLE" >/dev/null 2>&1 || true
    elif [ -x "/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister" ]; then
        /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister \
            -f "$APP_BUNDLE" >/dev/null 2>&1 || true
    fi

    MACOS_APP_BUNDLE="$APP_BUNDLE"
fi

# 9. Check PATH
PATH_INCLUDED=false
case ":$PATH:" in
    *":$BIN_DIR:"*) PATH_INCLUDED=true ;;
esac

printf "\n"
log_ok "Poly Studio installed successfully for $PLATFORM_DESC!"
printf "  ${GRAY}Binary:${NC}   %s/PolyStudio\n" "$INSTALL_DIR"
printf "  ${GRAY}Command:${NC}  %s/polystudio\n" "$BIN_DIR"
if [ -n "${MACOS_APP_BUNDLE:-}" ]; then
    printf "  ${GRAY}App:${NC}      %s (Launchpad, Spotlight & Dock)\n" "$MACOS_APP_BUNDLE"
fi
if [ -n "${DESKTOP_SHORTCUT:-}" ]; then
    printf "  ${GRAY}Desktop:${NC}  %s\n" "$DESKTOP_SHORTCUT"
fi
if [ "$PLATFORM" = "linux" ]; then
    printf "  ${GRAY}Menu:${NC}      ~/.local/share/applications/polystudio.desktop\n"
fi
printf "\n"

if [ "$PATH_INCLUDED" = false ]; then
    printf "${YELLOW}Note:${NC} '%s' is not in your current PATH.\n" "$BIN_DIR"
    printf "Add it to your shell configuration (e.g. ~/.bashrc or ~/.zshrc):\n"
    printf "  ${CYAN}export PATH=\"%s:\$PATH\"${NC}\n\n" "$BIN_DIR"
    printf "Or run directly:\n"
    printf "  ${CYAN}%s/polystudio${NC}\n\n" "$BIN_DIR"
else
    printf "To launch Poly Studio, simply run:\n"
    printf "  ${CYAN}polystudio${NC}\n\n"
fi
