#!/bin/bash

# Function to check and install required utilities
check_and_install_deps() {
    local deps=("skopeo" "jq" "grep" "sort" "head")
    local missing_deps=()

    # Check availability of each utility
    for dep in "${deps[@]}"; do
        if ! command -v "$dep" &> /dev/null; then
            missing_deps+=("$dep")
        fi
    done

    # If all utilities are installed, exit
    if [ ${#missing_deps[@]} -eq 0 ]; then
        echo "✓ All required utilities are installed."
        return 0
    fi

    echo "❌ The following utilities are missing: ${missing_deps[*]}"
    echo "🔍 Attempting to install..."

    # Determine package manager and install missing utilities
    if command -v apt &> /dev/null; then
        # Debian/Ubuntu
        sudo apt update
        sudo apt install -y "${missing_deps[@]}"
    elif command -v apt-get &> /dev/null; then
        # Debian/Ubuntu (alternative)
        sudo apt-get update
        sudo apt-get install -y "${missing_deps[@]}"
    elif command -v pacman &> /dev/null; then
        # Arch Linux
        for dep in "${missing_deps[@]}"; do
            case $dep in
                "skopeo")
                    sudo pacman -S --noconfirm skopeo
                    ;;
                "jq")
                    sudo pacman -S --noconfirm jq
                    ;;
                "grep"|"sort"|"head")
                    # These utilities are usually part of coreutils
                    sudo pacman -S --noconfirm coreutils
                    ;;
            esac
        done
    elif command -v apk &> /dev/null; then
        # Alpine Linux
        sudo apk add "${missing_deps[@]}"
    elif command -v yum &> /dev/null; then
        # RHEL/CentOS 7
        sudo yum install -y epel-release
        sudo yum install -y "${missing_deps[@]}"
    elif command -v dnf &> /dev/null; then
        # Fedora/RHEL 8+
        sudo dnf install -y "${missing_deps[@]}"
    elif command -v zypper &> /dev/null; then
        # openSUSE
        sudo zypper install -y "${missing_deps[@]}"
    else
        echo "❌ Could not determine package manager. Install utilities manually: ${missing_deps[*]}"
        exit 1
    fi

    # Check if utilities were installed successfully
    local failed_deps=()
    for dep in "${missing_deps[@]}"; do
        if ! command -v "$dep" &> /dev/null; then
            failed_deps+=("$dep")
        fi
    done

    if [ ${#failed_deps[@]} -gt 0 ]; then
        echo "❌ Failed to install: ${failed_deps[*]}"
        exit 1
    else
        echo "✓ All missing utilities were successfully installed."
    fi
}

# Function to display help
show_help() {
    echo "Usage: $0 <repository> [number_of_tags]"
    echo ""
    echo "Arguments:"
    echo "  <repository>      - Docker repository URL or name (required)"
    echo "  [number_of_tags]  - number of recent tags to keep (default: 3)"
    echo ""
    echo "Examples:"
    echo "  $0 docker.io/library/alpine"
    echo "  $0 myregistry.local:5000/myapp 5"
    echo "  $0 registry.example.com/project/image 10"
}

# Check for the first argument
if [ -z "$1" ]; then
    echo "❌ Error: repository not specified"
    echo ""
    show_help
    exit 1
fi

# Check and install dependencies
check_and_install_deps

# Set the number of tags to keep
KEEP_TAGS=${2:-3}

# Check that the number of tags is a positive number
if ! [[ "$KEEP_TAGS" =~ ^[0-9]+$ ]] || [ "$KEEP_TAGS" -lt 1 ]; then
    echo "❌ Error: number of tags must be a positive number"
    exit 1
fi

echo "🔍 Fetching list of tags for $1..."
echo "📦 Will keep $KEEP_TAGS recent tags (excluding latest)"

# Fetch all tags
allTags=$(skopeo list-tags docker://"$1" 2>/dev/null | jq -r '.Tags[]')

if [ -z "$allTags" ]; then
    echo "❌ Error: could not fetch tag list or repository is empty"
    exit 1
fi

# Count total number of tags
totalTags=$(echo "$allTags" | wc -l)

# Determine how many tags to delete
tagsToDelete=$((totalTags - KEEP_TAGS - 1)) # -1 for latest

if [ "$tagsToDelete" -le 0 ]; then
    echo "✓ Total tags: $totalTags (including latest)"
    echo "✓ Nothing to delete, keeping all $totalTags tags"
    exit 0
fi

# Get tags to delete (exclude latest and keep KEEP_TAGS recent ones)
oldTags=$(echo "$allTags" | grep -v "latest" | sort | head -n -"$KEEP_TAGS")

echo "📊 Total tags: $totalTags (including latest)"
echo "🗑️  Will be deleted: $(echo "$oldTags" | wc -l) tags"
echo ""

# Delete old tags
for tag in $oldTags; do
    echo "  ➜ Deleting: $tag"
    if skopeo delete docker://"$1:$tag" 2>/dev/null; then
        echo "    ✓ Successfully deleted"
    else
        echo "    ❌ Error deleting $tag"
    fi
done

echo ""
echo "✅ Done!"
echo "📝 Kept: $KEEP_TAGS recent tags and latest"
