#!/bin/sh
set -e

# Dockhand Docker Entrypoint
# === Configuration ===
PUID=${PUID:-1001}
PGID=${PGID:-1001}

# === Detect if running as root ===
RUNNING_AS_ROOT=false
if [ "$(id -u)" = "0" ]; then
    RUNNING_AS_ROOT=true
fi

# === Non-root mode (user: directive in compose) ===
# If container started as non-root, skip all user management and run directly
if [ "$RUNNING_AS_ROOT" = "false" ]; then
    echo "Running as user $(id -u):$(id -g) (set via container user directive)"

    # Ensure data directories exist (user must have write access to DATA_DIR via volume mount)
    DATA_DIR="${DATA_DIR:-/app/data}"
    if [ ! -d "$DATA_DIR/db" ]; then
        echo "Creating database directory at $DATA_DIR/db"
        mkdir -p "$DATA_DIR/db" 2>/dev/null || {
            echo "ERROR: Cannot create $DATA_DIR/db directory"
            echo "Ensure the data volume is mounted with correct permissions for user $(id -u):$(id -g)"
            echo ""
            echo "Example docker-compose.yml:"
            echo "  volumes:"
            echo "    - ./data:/app/data  # This directory must be writable by user $(id -u)"
            exit 1
        }
    fi
    if [ ! -d "$DATA_DIR/stacks" ]; then
        mkdir -p "$DATA_DIR/stacks" 2>/dev/null || true
    fi

    # Check Docker socket access if mounted
    SOCKET_PATH="/var/run/docker.sock"
    if [ -S "$SOCKET_PATH" ]; then
        if test -r "$SOCKET_PATH" 2>/dev/null; then
            echo "Docker socket accessible at $SOCKET_PATH"
            # Detect hostname from Docker if not set
            if [ -z "$DOCKHAND_HOSTNAME" ]; then
                DETECTED_HOSTNAME=$(curl -s --unix-socket "$SOCKET_PATH" http://localhost/info 2>/dev/null | sed -n 's/.*"Name":"\([^"]*\)".*/\1/p')
                if [ -n "$DETECTED_HOSTNAME" ]; then
                    export DOCKHAND_HOSTNAME="$DETECTED_HOSTNAME"
                    echo "Detected Docker host hostname: $DOCKHAND_HOSTNAME"
                fi
            fi
        else
            SOCKET_GID=$(stat -c '%g' "$SOCKET_PATH" 2>/dev/null || echo "unknown")
            echo "WARNING: Docker socket not readable by user $(id -u)"
            echo "Add --group-add $SOCKET_GID to your docker run command"
        fi
    else
        echo "No Docker socket found at $SOCKET_PATH"
        echo "Configure Docker environments via the web UI (Settings > Environments)"
    fi

    # Run directly as current user (no su-exec needed)
    if [ "$1" = "" ]; then
        exec bun run ./build/index.js
    else
        exec "$@"
    fi
fi

# === User Setup ===
# Root mode: PUID=0 requested OR already running as root with default PUID/PGID
if [ "$PUID" = "0" ]; then
    echo "Running as root user (PUID=0)"
    RUN_USER="root"
elif [ "$RUNNING_AS_ROOT" = "true" ] && [ "$PUID" = "1001" ] && [ "$PGID" = "1001" ]; then
    echo "Running as root user"
    RUN_USER="root"
else
    RUN_USER="dockhand"
    # Only modify if PUID/PGID differ from image defaults (1001:1001)
    if [ "$PUID" != "1001" ] || [ "$PGID" != "1001" ]; then
        echo "Configuring user with PUID=$PUID PGID=$PGID"

        # Remove existing dockhand user/group (using busybox commands)
        deluser dockhand 2>/dev/null || true
        delgroup dockhand 2>/dev/null || true

        # Check for UID conflicts - warn but don't delete other users
        SKIP_USER_CREATE=false
        EXISTING=$(awk -F: -v uid="$PUID" '$3 == uid { print $1 }' /etc/passwd)
        if [ -n "$EXISTING" ]; then
            if [ "$EXISTING" = "bun" ]; then
                echo "Note: UID $PUID is used by the 'bun' runtime user - reusing it for dockhand"
                echo "If upgrading from a previous version, you may need to fix data permissions:"
                echo "  chown -R $PUID:$PGID /path/to/your/data"
                RUN_USER="bun"
                SKIP_USER_CREATE=true
            else
                echo "WARNING: UID $PUID already in use by '$EXISTING'. Using default UID 1001."
                PUID=1001
            fi
        fi

        # Handle GID - reuse existing group or create new
        TARGET_GROUP=$(awk -F: -v gid="$PGID" '$3 == gid { print $1 }' /etc/group)
        if [ -z "$TARGET_GROUP" ]; then
            addgroup -g "$PGID" dockhand
            TARGET_GROUP="dockhand"
        fi

        if [ "$SKIP_USER_CREATE" = "false" ]; then
            adduser -u "$PUID" -G "$TARGET_GROUP" -h /home/dockhand -D dockhand
        fi
    fi

    # === Directory Ownership ===
    # Only chown Dockhand's own subdirectories, not the entire /app/data tree.
    # Recursive chown on /app/data breaks stack volumes mounted with relative paths
    # (e.g. ./postgresql:/var/lib/postgresql) that need different ownership (#719).
    DATA_DIR="${DATA_DIR:-/app/data}"
    chown "$RUN_USER":"$RUN_USER" "$DATA_DIR" 2>/dev/null || true
    for subdir in db stacks git-repos tmp icons snapshots scanner-cache; do
        if [ -d "$DATA_DIR/$subdir" ]; then
            chown -R "$RUN_USER":"$RUN_USER" "$DATA_DIR/$subdir" 2>/dev/null || true
        fi
    done
    if [ "$RUN_USER" = "dockhand" ]; then
        chown -R dockhand:dockhand /home/dockhand 2>/dev/null || true
    fi

    if [ -n "$DATA_DIR" ] && [ "$DATA_DIR" != "/app/data" ] && [ "$DATA_DIR" != "./data" ]; then
        mkdir -p "$DATA_DIR"
        chown "$RUN_USER":"$RUN_USER" "$DATA_DIR" 2>/dev/null || true
        for subdir in db stacks git-repos tmp icons snapshots scanner-cache; do
            if [ -d "$DATA_DIR/$subdir" ]; then
                chown -R "$RUN_USER":"$RUN_USER" "$DATA_DIR/$subdir" 2>/dev/null || true
            fi
        done
    fi
fi

# === Docker Socket Access (Optional) ===
# Check if Docker socket is mounted and accessible
# Note: DOCKER_HOST with tcp:// requires configuring an environment via the web UI
SOCKET_PATH="/var/run/docker.sock"

if [ -S "$SOCKET_PATH" ]; then
    if [ "$RUN_USER" != "root" ]; then
        # Get socket GID
        SOCKET_GID=$(stat -c '%g' "$SOCKET_PATH" 2>/dev/null || echo "")

        if [ -n "$SOCKET_GID" ]; then
            # Check if user already has access
            if ! su-exec "$RUN_USER" test -r "$SOCKET_PATH" 2>/dev/null; then
                echo "Docker socket GID: $SOCKET_GID - adding $RUN_USER to docker group..."

                # Check if group with this GID exists (without getent, use /etc/group)
                DOCKER_GROUP=$(awk -F: -v gid="$SOCKET_GID" '$3 == gid { print $1 }' /etc/group)
                if [ -z "$DOCKER_GROUP" ]; then
                    # Create docker group with socket's GID
                    DOCKER_GROUP="docker"
                    addgroup -g "$SOCKET_GID" "$DOCKER_GROUP" 2>/dev/null || true
                fi

                # Add user to docker group (try both busybox variants)
                addgroup "$RUN_USER" "$DOCKER_GROUP" 2>/dev/null || \
                adduser "$RUN_USER" "$DOCKER_GROUP" 2>/dev/null || true

                # Verify access after adding to group
                if su-exec "$RUN_USER" test -r "$SOCKET_PATH" 2>/dev/null; then
                    echo "Docker socket accessible at $SOCKET_PATH"
                else
                    echo "WARNING: Could not grant Docker socket access to $RUN_USER"
                    echo "Try running container with: --group-add $SOCKET_GID"
                fi
            else
                echo "Docker socket accessible at $SOCKET_PATH"
            fi
        fi
    else
        echo "Docker socket accessible at $SOCKET_PATH"
    fi

    # === Detect Docker Host Hostname (for license validation) ===
    # Query Docker API to get the real host hostname (not container ID)
    if [ -z "$DOCKHAND_HOSTNAME" ]; then
        DETECTED_HOSTNAME=$(curl -s --unix-socket "$SOCKET_PATH" http://localhost/info 2>/dev/null | sed -n 's/.*"Name":"\([^"]*\)".*/\1/p')
        if [ -n "$DETECTED_HOSTNAME" ]; then
            export DOCKHAND_HOSTNAME="$DETECTED_HOSTNAME"
            echo "Detected Docker host hostname: $DOCKHAND_HOSTNAME"
        fi
    else
        echo "Using configured hostname: $DOCKHAND_HOSTNAME"
    fi
else
    echo "No local Docker socket mounted (this is normal when using socket-proxy or remote Docker)"
    echo "Configure your Docker environment via the web UI: Settings > Environments"
fi

# === Run Application ===
if [ "$RUN_USER" = "root" ]; then
    # Running as root - execute directly
    if [ "$1" = "" ]; then
        exec bun run ./build/index.js
    else
        exec "$@"
    fi
else
    # Running as non-root user
    echo "Running as user: $RUN_USER"
    if [ "$1" = "" ]; then
        exec su-exec "$RUN_USER" bun run ./build/index.js
    else
        exec su-exec "$RUN_USER" "$@"
    fi
fi
