#!/bin/bash
list="rancher-images.txt"
images="rancher-images.tar.gz"
source_registry=""

usage () {
    echo "USAGE: $0 [--image-list rancher-images.txt] [--images rancher-images.tar.gz]"
    echo "  [-s|--source-registry] source registry to pull images from in registry:port format."
    echo "  [-l|--image-list path] text file with list of images; one image per line."
    echo "  [-i|--images path] tar.gz generated by docker save."
    echo "  [-h|--help] Usage message"
}

POSITIONAL=()
while [[ $# -gt 0 ]]; do
    key="$1"
    case $key in
        -i|--images)
        images="$2"
        shift # past argument
        shift # past value
        ;;
        -l|--image-list)
        list="$2"
        shift # past argument
        shift # past value
        ;;
        -s|--source-registry)
        source_registry="$2"
        shift # past argument
        shift # past value
        ;;
        -h|--help)
        help="true"
        shift
        ;;
        *)
        usage
        exit 1
        ;;
    esac
done

if [[ $help ]]; then
    usage
    exit 0
fi

source_registry="${source_registry%/}"
if [ ! -z "${source_registry}" ]; then
    source_registry="${source_registry}/"
fi

docker_uses_containerd_snapshotter () {
    docker info 2>/dev/null | grep -qi "containerd.snapshotter"
}

helm_available () {
    command -v helm >/dev/null 2>&1
}

helm_oci_ga () {
    local v major minor
    v=$(helm version --short 2>/dev/null | sed -n 's/^v\([0-9.]*\).*/\1/p')
    [ -z "$v" ] && return 1
    major=${v%%.*}
    minor=${v#*.}; minor=${minor%%.*}
    [ "$major" -gt 3 ] || { [ "$major" -eq 3 ] && [ "$minor" -ge 8 ]; }
}

is_oci_helm_chart () {
    [[ "$1" == *"rancher/charts/"* ]]
}

# Preflight: rancher-images.txt now ships OCI Helm chart entries that
# 'docker pull' cannot handle unless the daemon uses the containerd
# snapshotter. If the host has neither the snapshotter nor the helm CLI, fail
# fast with a clear message instead of producing cryptic media-type errors.
has_oci_charts=false
while IFS= read -r i; do
    [ -z "${i}" ] && continue
    if is_oci_helm_chart "${i}"; then
        has_oci_charts=true
        break
    fi
done < "${list}"

use_helm_for_charts=false
if $has_oci_charts; then
    if ! docker_uses_containerd_snapshotter; then
        if helm_available; then
            if ! helm_oci_ga; then
                echo "====================================================================="
                echo "ERROR: helm CLI is older than v3.8.0; OCI chart support requires helm 3.8.0+ (GA)."
                echo ""
                echo "Please upgrade helm to v3.8.0 or later:"
                echo "    https://helm.sh/docs/intro/install/"
                echo ""
                echo "For reference, older versions need HELM_EXPERIMENTAL_OCI=1 and are not supported here:"
                echo "    v3.7.2 - last pre-GA (OCI works only with HELM_EXPERIMENTAL_OCI=1)"
                echo "    v3.6.3 - older experimental-OCI"
                echo "    v3.4.2 - OCI very limited"
                echo "====================================================================="
                exit 1
            fi
            echo "WARNING: Docker is not using the containerd snapshotter; falling back to helm CLI for OCI Helm charts."
            use_helm_for_charts=true
        else
            echo "====================================================================="
            echo "ERROR: List contains non-image OCI artifacts, which are not supported"
            echo "by docker's legacy storage drivers. You must take action in order to continue."
            echo ""
            echo "Preferred: configure docker to use the containerd image store"
            echo "    https://docs.docker.com/engine/storage/containerd/#enable-containerd-image-store-on-docker-engine"
            echo "    NOTE: Switching image stores hides all images and containers currently present in the original docker image store."
            echo ""
            echo "Alternative: install the helm CLI:"
            echo "    https://helm.sh/docs/intro/install/"
            echo "====================================================================="
            exit 1
        fi
    fi
fi

if $use_helm_for_charts; then
    mkdir -p ./rancher-oci-charts
fi

pulled=""
while IFS= read -r i; do
    [ -z "${i}" ] && continue
    i="${source_registry}${i}"
    if $use_helm_for_charts && is_oci_helm_chart "${i}"; then
        chart_version="${i#*:}"
        echo "Pulling chart: ${i}..."
        helm_error=$(helm pull "oci://${i%:*}" --version "${chart_version//_/+}" -d ./rancher-oci-charts 2>&1)
        if [ $? -eq 0 ]; then
            echo "Chart pull success: ${i}"
        else
            echo "Chart pull FAILED: ${i}"
            echo "Error output:"
            echo "${helm_error}"
            echo ""
            echo "ERROR: OCI Helm charts are required for Prime functionality."
            echo "Cannot proceed with incomplete artifact set."
            exit 1
        fi
        continue
    fi
    if docker pull "${i}" > /dev/null 2>&1; then
        echo "Image pull success: ${i}"
        pulled="${pulled} ${i}"
    else
        if docker inspect "${i}" > /dev/null 2>&1; then
            pulled="${pulled} ${i}"
        else
            echo "Image pull failed: ${i}"
        fi
    fi
done < "${list}"

if [ -n "${pulled}" ]; then
    echo "Creating ${images} with $(echo ${pulled} | wc -w | tr -d '[:space:]') images"
    docker save $(echo ${pulled}) | gzip --stdout > ${images}
else
    echo "No docker images pulled; skipping ${images}."
fi

if $use_helm_for_charts; then
    chart_count=$(ls ./rancher-oci-charts/*.tgz 2>/dev/null | wc -l)
    echo ""
    echo "OCI Helm charts saved in ./rancher-oci-charts/ (${chart_count} files). Used by rancher-load-images.sh. Remove with: rm -rf ./rancher-oci-charts"
fi
