#!/bin/bash
# install-docker.sh - Turnkey Pulse installation for Docker hosts
# This script installs pulse-sensor-proxy and generates docker-compose.yml

set -euo pipefail

PULSE_IMAGE="${PULSE_IMAGE:-rcourtman/pulse:latest}"
PULSE_PORT="${PULSE_PORT:-7655}"
PULSE_PROXY_CHANNEL="${PULSE_PROXY_CHANNEL:-stable}"
DETERMINED_PROXY_VERSION=""
PROXY_INSTALLER_SOURCE_LABEL="unset"
PROXY_ARCH_LABEL=""

compute_proxy_arch_label() {
    local arch
    arch=$(uname -m)
    case "$arch" in
        x86_64)
            PROXY_ARCH_LABEL="linux-amd64"
            ;;
        aarch64 | arm64)
            PROXY_ARCH_LABEL="linux-arm64"
            ;;
        armv7l | armhf)
            PROXY_ARCH_LABEL="linux-armv7"
            ;;
        *)
            PROXY_ARCH_LABEL=""
            ;;
    esac
}

set_github_fallback_url() {
    local ref="$1"
    if [[ -z "$PROXY_ARCH_LABEL" ]]; then
        return
    fi

    local base=""
    if [[ "$ref" == "main" ]]; then
        # Use latest release for main branch
        base="https://github.com/rcourtman/Pulse/releases/latest/download/pulse-sensor-proxy-${PROXY_ARCH_LABEL}"
    else
        base="https://github.com/rcourtman/Pulse/releases/download/${ref}/pulse-sensor-proxy-${PROXY_ARCH_LABEL}"
    fi

    export PULSE_SENSOR_PROXY_FALLBACK_URL="$base"
}

EMBEDDED_INSTALLER_ARCHIVE_B64=$(cat <<'EOF'
[encoded data, 13195 characters]
gku2hlcWM4oUtD4RVz1wCc5C6/5z0WqojsB3ZLbufwAW3BcGw6AAAA==
EOF
)

determine_proxy_release() {
    if [[ -n "${PULSE_PROXY_VERSION:-}" ]]; then
        DETERMINED_PROXY_VERSION="${PULSE_PROXY_VERSION}"
        return 0
    fi

    local channel="${PULSE_PROXY_CHANNEL:-stable}"
    local tag=""
    local api_url=""

    if command -v curl >/dev/null 2>&1; then
        if [[ "$channel" == "rc" ]]; then
            api_url="https://api.github.com/repos/rcourtman/Pulse/releases"
            tag=$(curl -fsSL --connect-timeout 5 --max-time 15 "$api_url" 2>/dev/null | grep '"tag_name":' | head -1 | sed -E 's/.*"([^"]+)".*/\1/' || true)
        else
            api_url="https://api.github.com/repos/rcourtman/Pulse/releases/latest"
            tag=$(curl -fsSL --connect-timeout 5 --max-time 15 "$api_url" 2>/dev/null | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/' || true)
        fi
    fi

    if [[ -n "$tag" ]]; then
        DETERMINED_PROXY_VERSION="$tag"
        return 0
    fi

    DETERMINED_PROXY_VERSION="main"
    return 1
}

download_installer_from_local() {
    local destination="$1"
    local base_url="${PULSE_SERVER:-http://localhost:7655}"
    local url="${base_url%/}/api/install/install-sensor-proxy.sh"

    if curl --fail --silent --location --connect-timeout 5 --max-time 20 "$url" -o "$destination" 2>/dev/null; then
        chmod +x "$destination"
        PROXY_INSTALLER_SOURCE_LABEL="local"
        export PULSE_SENSOR_PROXY_FALLBACK_URL="${base_url%/}/api/install/pulse-sensor-proxy"
        echo "  ✓ Downloaded proxy installer from ${url}"
        return 0
    fi

    echo "  ⚠️  Unable to download proxy installer from ${url}"
    return 1
}

download_installer_from_github() {
    local destination="$1"
    determine_proxy_release
    local tag="$DETERMINED_PROXY_VERSION"
    local ref="$tag"
    local attempted=false

    if [[ "$tag" == "main" ]]; then
        ref="main"
    fi

    if [[ "$tag" != "main" ]]; then
        local asset_url="https://github.com/rcourtman/Pulse/releases/download/${tag}/install-sensor-proxy.sh"
        attempted=true
        if curl --fail --silent --location --connect-timeout 5 --max-time 30 "$asset_url" -o "$destination" 2>/dev/null; then
            chmod +x "$destination"
            PROXY_INSTALLER_SOURCE_LABEL="github:${tag}"
            set_github_fallback_url "$tag"
            echo "  ✓ Downloaded proxy installer from ${asset_url}"
            return 0
        fi
    fi

    local release_url="https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh"
    attempted=true
    if curl --fail --silent --location --connect-timeout 5 --max-time 30 "$release_url" -o "$destination" 2>/dev/null; then
        chmod +x "$destination"
        PROXY_INSTALLER_SOURCE_LABEL="github:latest"
        set_github_fallback_url "main"
        echo "  ✓ Downloaded proxy installer from ${release_url}"
        return 0
    fi

    if [[ "$attempted" == true ]]; then
        echo "  ⚠️  Unable to download proxy installer from GitHub (tag=${tag})"
    fi
    return 1
}

write_embedded_installer() {
    local destination="$1"

    if ! command -v base64 >/dev/null 2>&1; then
        echo "  ⚠️  base64 command not available; cannot use embedded installer"
        return 1
    fi

    if ! command -v gzip >/dev/null 2>&1; then
        echo "  ⚠️  gzip command not available; cannot use embedded installer"
        return 1
    fi

    local decode_output
    if decode_output=$(printf '%s' "$EMBEDDED_INSTALLER_ARCHIVE_B64" | base64 -d 2>&1 | gzip -dc 2>&1 >"$destination"); then
        chmod +x "$destination"
        PROXY_INSTALLER_SOURCE_LABEL="embedded"
        echo "  ✓ Used embedded proxy installer fallback"
        return 0
    fi

    echo "  ⚠️  Embedded proxy installer fallback failed"
    if [[ -n "$decode_output" ]]; then
        echo "      → $decode_output"
    fi
    return 1
}

download_proxy_installer() {
    local destination="$1"

    if download_installer_from_local "$destination"; then
        return 0
    fi

    echo "  Attempting GitHub fallback..."
    if download_installer_from_github "$destination"; then
        return 0
    fi

    echo "  Attempting embedded installer fallback..."
    if write_embedded_installer "$destination"; then
        return 0
    fi

    return 1
}


# ============================================
# Helper Functions
# ============================================

validate_socket() {
    local socket_path="$1"

    # Check if it's a socket file
    if [ ! -S "$socket_path" ]; then
        return 1
    fi

    # Test if we can connect to it (using timeout to avoid hangs)
    if command -v socat &>/dev/null; then
        if timeout 2 socat -u OPEN:/dev/null UNIX-CONNECT:"$socket_path" 2>/dev/null; then
            return 0
        else
            return 1
        fi
    fi

    # If socat not available, assume socket is valid if it exists as a socket
    return 0
}

# ============================================
# Pre-flight Checks
# ============================================

compute_proxy_arch_label

echo "============================================"
echo "  Pulse Turnkey Docker Installation"
echo "============================================"
echo ""

# Check if running as root (early check for better error messages)
if [ "$EUID" -ne 0 ]; then
    echo "❌ ERROR: This script must be run as root"
    echo ""
    echo "Please run: sudo $0"
    exit 1
fi

# Detect if running in a container
if [ -f /.dockerenv ] || [ -f /run/.containerenv ]; then
    echo "❌ ERROR: This script must run on the Docker host, not inside a container"
    echo ""
    echo "Please run this script on your Docker host machine."
    exit 1
fi

# Check if Docker is installed
if ! command -v docker &> /dev/null; then
    echo "❌ ERROR: Docker is not installed"
    echo ""
    echo "Please install Docker first:"
    echo "  curl -fsSL https://get.docker.com | sh"
    exit 1
fi

# Check if docker compose is available
if ! docker compose version &> /dev/null; then
    echo "⚠️  Warning: 'docker compose' command not found"
    echo "   You may need to use 'docker-compose' instead"
    echo ""
fi

# ============================================
# Socket Detection & Deconfliction
# ============================================

BIND_MOUNT_SOCKET="/mnt/pulse-proxy/pulse-sensor-proxy.sock"
LOCAL_SOCKET="/run/pulse-sensor-proxy/pulse-sensor-proxy.sock"
SOCKET_PATH=""
SKIP_INSTALLATION=false
LOCAL_PROXY_EXISTED_AT_START=false

echo "Checking for existing pulse-sensor-proxy..."
echo ""

# Check for bind-mounted socket (LXC scenario)
if [ -S "$BIND_MOUNT_SOCKET" ]; then
    echo "  Found socket at /mnt/pulse-proxy (bind-mounted from host)"
    if validate_socket "$BIND_MOUNT_SOCKET"; then
        echo "  ✓ Socket is functional"
        SOCKET_PATH="/mnt/pulse-proxy"
        SKIP_INSTALLATION=true

        # Deconflict: if local proxy also exists, stop it
        if systemctl is-active --quiet pulse-sensor-proxy 2>/dev/null; then
            echo "  ⚠️  Found conflicting local pulse-sensor-proxy service"
            echo "     Stopping local service to avoid conflicts..."
            systemctl stop pulse-sensor-proxy
            systemctl disable pulse-sensor-proxy 2>/dev/null || true
        fi
    else
        echo "  ⚠️  Socket exists but is not responsive - will install local proxy"
        SKIP_INSTALLATION=false
    fi
fi

# Check for existing local installation
if [ -S "$LOCAL_SOCKET" ] && [ "$SKIP_INSTALLATION" = false ]; then
    echo "  Found socket at /run/pulse-sensor-proxy (local installation)"
    LOCAL_PROXY_EXISTED_AT_START=true
    if validate_socket "$LOCAL_SOCKET"; then
        echo "  ✓ Socket is functional - will refresh to update tokens/config"
        SOCKET_PATH="/run/pulse-sensor-proxy"
        # Don't skip installation - always reinstall to refresh tokens
        SKIP_INSTALLATION=false
    else
        echo "  ⚠️  Socket exists but is not responsive - will reinstall"
        systemctl stop pulse-sensor-proxy 2>/dev/null || true
        SKIP_INSTALLATION=false
    fi
fi

# ============================================
# Proxy Installation (if needed)
# ============================================

if [ "$SKIP_INSTALLATION" = true ]; then
    echo ""
    echo "✓ Using existing pulse-sensor-proxy at ${SOCKET_PATH}"
    echo ""
else
    echo "  No functional socket found - installing pulse-sensor-proxy..."
    echo ""

    # Download and run the proxy installer
    PROXY_INSTALLER="/tmp/install-sensor-proxy-$$.sh"

    unset PULSE_SENSOR_PROXY_FALLBACK_URL

    if ! download_proxy_installer "$PROXY_INSTALLER"; then
        echo "❌ ERROR: Could not obtain pulse-sensor-proxy installer"
        echo ""
        echo "Sources attempted:"
        echo "  • ${PULSE_SERVER:-http://localhost:7655}/api/install/install-sensor-proxy.sh"
        if [[ -n "$DETERMINED_PROXY_VERSION" ]]; then
            echo "  • GitHub release/tag: ${DETERMINED_PROXY_VERSION}"
        else
            echo "  • GitHub releases (auto-detected)"
        fi
        echo "  • Embedded fallback installer"
        echo ""
        echo "Hints:"
        echo "  1. Ensure network connectivity to the Pulse host or GitHub."
        echo "  2. Set PULSE_PROXY_VERSION (e.g. v4.24.0) to pin a specific release."
        echo "  3. Confirm curl is allowed through firewalls/proxies."
        rm -f "$PROXY_INSTALLER"
        exit 1
    fi

    case "$PROXY_INSTALLER_SOURCE_LABEL" in
        local)
            # already set during download
            ;;
        github:*)
            # fallback URL set in download helper
            ;;
        *)
            unset PULSE_SENSOR_PROXY_FALLBACK_URL
            ;;
    esac

    # Run installer in standalone mode (no container)
    if ! "$PROXY_INSTALLER" --standalone --pulse-server "${PULSE_SERVER:-http://localhost:7655}" --quiet; then
        echo "❌ Proxy installation failed"
        rm -f "$PROXY_INSTALLER"
        exit 1
    fi

    rm -f "$PROXY_INSTALLER"

    echo ""
    echo "✓ pulse-sensor-proxy installed successfully"
    echo ""

    # Validate newly installed socket
    if ! validate_socket "$LOCAL_SOCKET"; then
        echo "⚠️  Warning: Proxy installed but socket is not responsive"
        echo "   Temperature monitoring may not work correctly"
        echo ""
    fi

    SOCKET_PATH="/run/pulse-sensor-proxy"
fi

# ============================================
# Final Socket Validation
# ============================================

if [ -z "$SOCKET_PATH" ]; then
    echo "❌ ERROR: No functional socket available after installation"
    echo ""
    echo "Please check:"
    echo "  1. systemctl status pulse-sensor-proxy"
    echo "  2. journalctl -u pulse-sensor-proxy -n 50"
    exit 1
fi

# ============================================
# Generate Docker Compose Configuration
# ============================================

COMPOSE_FILE="./docker-compose.yml"

# Check if docker-compose.yml already exists (idempotency)
if [ -f "$COMPOSE_FILE" ]; then
    echo "⚠️  docker-compose.yml already exists"
    echo "   Backing up to docker-compose.yml.backup"
    cp "$COMPOSE_FILE" "${COMPOSE_FILE}.backup"
fi

cat > "$COMPOSE_FILE" << 'COMPOSE_EOF'
version: '3.8'

services:
  pulse:
    image: ${PULSE_IMAGE:-rcourtman/pulse:latest}
    container_name: pulse
    restart: unless-stopped
    user: "1000:1000"
    security_opt:
      - apparmor=unconfined
    ports:
      - "${PULSE_PORT:-7655}:7655"
    volumes:
      - pulse-data:/data
      # Secure temperature monitoring via host-side proxy
COMPOSE_EOF

# Add socket mount with detected path
echo "      - ${SOCKET_PATH}:/mnt/pulse-proxy:ro" >> "$COMPOSE_FILE"

# Continue compose file
cat >> "$COMPOSE_FILE" << 'COMPOSE_EOF'
    environment:
      - TZ=${TZ:-UTC}
    healthcheck:
      test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:7655/api/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

volumes:
  pulse-data:
    driver: local
COMPOSE_EOF

echo "✓ Generated docker-compose.yml"
echo "  Socket mount: ${SOCKET_PATH}:/mnt/pulse-proxy:ro"
echo ""

# Create .env file with defaults
ENV_FILE=".env"
if [ -f "$ENV_FILE" ]; then
    echo "⚠️  .env file already exists - not overwriting"
    echo ""
else
    cat > "$ENV_FILE" << EOF
PULSE_IMAGE=${PULSE_IMAGE}
PULSE_PORT=${PULSE_PORT}
TZ=$(timedatectl show -p Timezone --value 2>/dev/null || echo "UTC")
EOF
    echo "✓ Generated .env file"
    echo ""
fi

# ============================================
# Installation Complete
# ============================================

echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "✅ Installation Complete!"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "Socket location: ${SOCKET_PATH}"
echo ""
echo "Start Pulse with:"
echo "  docker compose up -d"
echo ""
echo "Or with docker run:"
echo "  docker run -d \\"
echo "    --name pulse \\"
echo "    --user 1000:1000 \\"
echo "    --security-opt apparmor=unconfined \\"
echo "    --restart unless-stopped \\"
echo "    -p ${PULSE_PORT}:7655 \\"
echo "    -v pulse-data:/data \\"
echo "    -v ${SOCKET_PATH}:/mnt/pulse-proxy:ro \\"
echo "    ${PULSE_IMAGE}"
echo ""
echo "Access Pulse at: http://$(hostname -I | awk '{print $1}'):${PULSE_PORT}"
echo ""
echo "Features enabled:"
echo "  ✓ Secure temperature monitoring (via host-side proxy)"
echo "  ✓ Automatic restarts"
echo "  ✓ Persistent data storage"
echo ""
