#!/bin/bash
# Devcontainer Overlay
# Applies settings parsed from devcontainer.json:
#   - Environment variables
#   - Lifecycle commands (onCreate, postCreate, postStart)
#   - Feature-based package installation
#
# Reads state from: $STATE_DIR/$container.devcontainer.json
# (written by dx before container creation)
#
# Usage: Called by dev.sh during container creation
#   apply_devcontainer_overlay <container_name>

set -e

OVERLAY_NAME="devcontainer"

# Map known feature URIs to apt packages
declare -A FEATURE_PACKAGES=(
    ["git"]="git"
    ["github-cli"]="gh"
    ["common-utils"]="curl wget ca-certificates gnupg"
    ["python"]=""      # handled by python overlay
    ["node"]=""        # handled by node overlay
    ["rust"]=""        # handled by rust overlay
    ["go"]=""          # handled by go overlay
)

# Features that we warn about (can't support in nspawn)
UNSUPPORTED_FEATURES=(
    "docker-in-docker"
    "docker-outside-of-docker"
    "kubernetes-helm"
)

apply_devcontainer_overlay() {
    local container="$1"
    local state_file="$STATE_DIR/$container.devcontainer.json"

    echo "[OVERLAY] Applying devcontainer overlay to $container..."

    if [[ ! -f "$state_file" ]]; then
        echo "[OVERLAY] No devcontainer state file found at $state_file, skipping"
        return 0
    fi

    # Verify jq is available on host
    if ! command -v jq &>/dev/null; then
        echo "[OVERLAY] WARNING: jq not found on host, cannot parse devcontainer state"
        return 0
    fi

    # --- 1. Environment variables ---
    local env_json
    env_json=$(jq -r '.env // {}' "$state_file")
    local env_count
    env_count=$(echo "$env_json" | jq 'length')

    if [[ "$env_count" -gt 0 ]]; then
        echo "[OVERLAY] Setting $env_count environment variable(s)..."

        # Build the env file content on host, inject into container
        local env_script=""
        while IFS='=' read -r key value; do
            # Escape for shell
            local escaped_value
            escaped_value=$(printf '%s' "$value" | sed "s/'/'\\\\''/g")
            env_script+="export ${key}='${escaped_value}'"$'\n'
        done < <(echo "$env_json" | jq -r 'to_entries[] | "\(.key)=\(.value)"')

        sudo machinectl shell "$container" /bin/bash -c "
cat > /etc/profile.d/devcontainer-env.sh << 'ENVEOF'
# Generated by devcontainer overlay
${env_script}ENVEOF
chmod 644 /etc/profile.d/devcontainer-env.sh

# Also add to dev user's bashrc for non-login shells
cat >> /home/dev/.bashrc << 'ENVEOF'

# Devcontainer environment variables
source /etc/profile.d/devcontainer-env.sh
ENVEOF
"
    fi

    # --- 2. Feature-based packages ---
    local features_json
    features_json=$(jq -r '.features // {}' "$state_file")
    local features_count
    features_count=$(echo "$features_json" | jq 'length')

    if [[ "$features_count" -gt 0 ]]; then
        echo "[OVERLAY] Processing $features_count feature(s)..."

        local packages_to_install=""

        while IFS= read -r feature_uri; do
            local matched=false

            # Check for unsupported features
            for unsupported in "${UNSUPPORTED_FEATURES[@]}"; do
                if [[ "$feature_uri" == *"$unsupported"* ]]; then
                    echo "[OVERLAY] WARNING: Feature '$feature_uri' is not supported in nspawn containers"
                    matched=true
                    break
                fi
            done
            $matched && continue

            # Check for known features
            for feature_name in "${!FEATURE_PACKAGES[@]}"; do
                if [[ "$feature_uri" == *"$feature_name"* ]]; then
                    local pkgs="${FEATURE_PACKAGES[$feature_name]}"
                    if [[ -n "$pkgs" ]]; then
                        packages_to_install+=" $pkgs"
                    fi
                    matched=true
                    break
                fi
            done

            if ! $matched; then
                echo "[OVERLAY] WARNING: Unknown feature '$feature_uri' (skipping)"
            fi
        done < <(echo "$features_json" | jq -r 'keys[]')

        if [[ -n "$packages_to_install" ]]; then
            echo "[OVERLAY] Installing feature packages:$packages_to_install"
            sudo machinectl shell "$container" /bin/bash -c "
DEBIAN_FRONTEND=noninteractive apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -y $packages_to_install
"
        fi
    fi

    # --- 3. onCreateCommand ---
    local on_create_cmd
    on_create_cmd=$(jq -r '.onCreateCommand // empty' "$state_file")

    if [[ -n "$on_create_cmd" ]]; then
        echo "[OVERLAY] Running onCreateCommand..."
        sudo machinectl shell "$container" /bin/bash -c "
su - dev -c $(printf '%q' "$on_create_cmd")
" || echo "[OVERLAY] WARNING: onCreateCommand failed (non-fatal)"
    fi

    # --- 4. postCreateCommand ---
    local post_create_cmd
    post_create_cmd=$(jq -r '.postCreateCommand // empty' "$state_file")

    if [[ -n "$post_create_cmd" ]]; then
        echo "[OVERLAY] Running postCreateCommand..."
        sudo machinectl shell "$container" /bin/bash -c "
su - dev -c $(printf '%q' "$post_create_cmd")
" || echo "[OVERLAY] WARNING: postCreateCommand failed (non-fatal)"
    fi

    # --- 5. postStartCommand (saved for run-on-boot) ---
    local post_start_cmd
    post_start_cmd=$(jq -r '.postStartCommand // empty' "$state_file")

    if [[ -n "$post_start_cmd" ]]; then
        echo "[OVERLAY] Saving postStartCommand for run-on-boot..."
        sudo machinectl shell "$container" /bin/bash -c "
cat > /home/dev/.devcontainer-post-start.sh << 'PSEOF'
#!/bin/bash
# Generated by devcontainer overlay - runs once per boot
STAMP=\"/tmp/.devcontainer-post-start-done\"
if [[ -f \"\$STAMP\" ]]; then
    exit 0
fi
$(printf '%s' "$post_start_cmd")
touch \"\$STAMP\"
PSEOF
chmod 755 /home/dev/.devcontainer-post-start.sh
chown dev:dev /home/dev/.devcontainer-post-start.sh
"
    fi

    echo "[OVERLAY] Devcontainer overlay applied"
}

# Allow sourcing or direct execution
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    if [ -z "$1" ]; then
        echo "Usage: $0 <container_name>"
        exit 1
    fi
    apply_devcontainer_overlay "$1"
fi
