#!/bin/bash
# alpkg - Aaron Linux Package Manager
# Maintainer: endermanthecookie@gmail.com
# Repository: https://packages-aaron-linux.vercel.app
# Supports: .alp, .deb, .rpm, .pkg.tar.zst, APT repos, Pacman repos

DB="/var/lib/alpkg"
PKG_DIR="/var/packages"
CACHE="/var/cache/alpkg"
WORK_DIR="/tmp/alpkg-install"
CONF="/etc/alpkg/alpkg.conf"
REPO_INDEX="$CACHE/repo-index.json"

REPO_URL="https://packages-aaron-linux.vercel.app"

if [ -f "$CONF" ]; then
    . "$CONF"
fi

BOOTSTRAP_MARKER="$DB/.bootstrapped"

# ─── Bootstrap Logic ──────────────────────────────────────

detect_native_pm() {
    if   command -v apt-get >/dev/null 2>&1; then echo "apt"
    elif command -v dnf     >/dev/null 2>&1; then echo "dnf"
    elif command -v yum     >/dev/null 2>&1; then echo "yum"
    elif command -v zypper  >/dev/null 2>&1; then echo "zypper"
    elif command -v pacman  >/dev/null 2>&1; then echo "pacman"
    elif command -v apk     >/dev/null 2>&1; then echo "apk"
    else echo ""
    fi
}

pm_install() {
    local pm="$1"; shift
    case "$pm" in
        apt)    apt-get install -y "$@" 2>/dev/null ;;
        dnf)    dnf install -y "$@" 2>/dev/null ;;
        yum)    yum install -y "$@" 2>/dev/null ;;
        zypper) zypper install -y "$@" 2>/dev/null ;;
        pacman) pacman -S --noconfirm "$@" 2>/dev/null ;;
        apk)    apk add "$@" 2>/dev/null ;;
    esac
}

build_pacman() {
    local src="$CACHE/pacman-src"
    [ -d "$src" ] && rm -rf "$src"
    echo "Cloning pacman from https://gitlab.archlinux.org/pacman/pacman.git ..."
    git clone --depth=1 https://gitlab.archlinux.org/pacman/pacman.git "$src" 2>&1 || return 1
    cd "$src" || return 1
    if command -v meson >/dev/null 2>&1; then
        meson setup build 2>&1 && ninja -C build 2>&1 && ninja -C build install 2>&1
    else
        ./autogen.sh 2>/dev/null && ./configure --prefix=/usr 2>&1 && make -j$(nproc) 2>&1 && make install 2>&1
    fi
    local ret=$?
    cd /; rm -rf "$src"
    return $ret
}

build_apt() {
    local src="$CACHE/apt-src"
    [ -d "$src" ] && rm -rf "$src"
    echo "Cloning APT from https://salsa.debian.org/apt-team/apt.git ..."
    git clone --depth=1 https://salsa.debian.org/apt-team/apt.git "$src" 2>&1 || return 1
    cd "$src" || return 1
    if [ -f CMakeLists.txt ]; then
        cmake . 2>&1 && make -j$(nproc) 2>&1 && make install 2>&1
    else
        ./configure --prefix=/usr 2>&1 && make -j$(nproc) 2>&1 && make install 2>&1
    fi
    local ret=$?
    cd /; rm -rf "$src"
    return $ret
}

bootstrap() {
    echo "=== alpkg bootstrap ==="
    local pm; pm=$(detect_native_pm)
    [ -z "$pm" ] && { echo "Error: no supported package manager found. Install curl, git, and build tools manually."; return 1; }
    echo "Detected native package manager: $pm"

    for tool in curl git; do
        if ! command -v "$tool" >/dev/null 2>&1; then
            echo "Installing $tool..."
            pm_install "$pm" "$tool" || return 1
        fi
    done

    local build_pkgs=""
    case "$pm" in
        apt)    build_pkgs="gcc make meson ninja-build pkg-config cmake libarchive-dev libcurl4-openssl-dev libssl-dev gettext libzstd-dev liblz4-dev liblzma-dev libgpgme-dev libdb-dev";;
        dnf|yum) build_pkgs="gcc make meson ninja-build pkgconfig cmake libarchive-devel libcurl-devel openssl-devel gettext libzstd-devel liblz4-devel xz-devel gpgme-devel libdb-devel";;
        pacman) build_pkgs="base-devel meson ninja cmake libarchive curl openssl gettext zstd lz4 xz gpgme db";;
        zypper) build_pkgs="gcc make meson ninja pkg-config cmake libarchive-devel libcurl-devel openssl-devel gettext-tools libzstd-devel liblz4-devel xz-devel gpgme-devel libdb-devel";;
        apk)    build_pkgs="gcc make meson ninja cmake libarchive-dev curl-dev openssl-dev gettext zstd-dev lz4-dev xz-dev gpgme-dev db-dev";;
    esac
    echo "Installing build dependencies..."
    pm_install "$pm" $build_pkgs || echo "Warning: some build deps may not have installed" >&2

    if ! command -v pacman >/dev/null 2>&1 && ! command -v pacman-static >/dev/null 2>&1; then
        echo "--- Building pacman from source ---"
        build_pacman || echo "Warning: pacman build failed" >&2
    else
        echo "pacman already available"
    fi

    if ! command -v apt-cache >/dev/null 2>&1 && ! command -v apt-get >/dev/null 2>&1; then
        echo "--- Building APT from source ---"
        build_apt || echo "Warning: APT build failed" >&2
    else
        echo "APT already available"
    fi

    echo "=== Bootstrap complete ==="
    echo "Available backends:"
    command -v pacman >/dev/null 2>&1 && echo "  - pacman ($(pacman --version 2>&1 | head -1))"
    command -v apt-cache >/dev/null 2>&1 && echo "  - apt-cache"
    command -v apt-get >/dev/null 2>&1 && echo "  - apt-get"
    touch "$BOOTSTRAP_MARKER"
}

# ─── Help ─────────────────────────────────────────────────

help() {
    echo "alpkg - Aaron Linux Package Manager"
    echo "Maintainer: endermanthecookie@gmail.com"
    echo "Usage: alpkg <command> [options]"
    echo ""
    echo "Commands:"
    echo "  install <pkg>          Install package from any source"
    echo "    --alpkg              Only search alpkg repository"
    echo "    --apt                Only search APT repositories"
    echo "    --pacman             Only search Pacman repositories"
    echo "  remove <name>          Remove package (requires root)"
    echo "  list [options]         List all packages from all sources"
    echo "    --name <query>       Filter by name (case insensitive)"
    echo "    --platform <src>     Filter: alpkg, apt, or pacman"
    echo "  search <query>         Search available packages"
    echo "  bootstrap              Install/build missing backends (apt, pacman)"
    echo "  update                 Update package lists from all repos"
    echo "  info <pkg>             Show package info"
    echo "  repo                   Show current repository URL"
    echo "  repo set <url>         Set alpkg repository URL"
    echo "  convert <file>         Convert .deb/.rpm/.pkg.tar.zst to .alp"
    echo ""
    echo "Sources:"
    echo "  --alpkg  https://packages-aaron-linux.vercel.app (default)"
    echo "  --apt    Debian/Ubuntu repositories (auto-detected)"
    echo "  --pacman Arch Linux repositories (auto-detected)"
    echo ""
    echo "Examples:"
    echo "  alpkg list                              # all packages"
    echo "  alpkg list --name git                   # git-related"
    echo "  alpkg list --platform apt                # APT only"
    echo "  alpkg list --platform alpkg --name vim   # vim in alpkg"
}

# ─── Utilities ─────────────────────────────────────────────

download() {
    local url="$1" out="$2"
    if command -v curl >/dev/null 2>&1; then curl -fsSL "$url" -o "$out"
    elif command -v wget >/dev/null 2>&1; then wget -q "$url" -O "$out"
    else echo "Error: need curl or wget"; exit 1; fi
}

fetch_index() {
    mkdir -p "$CACHE"
    echo "Fetching alpkg index from $REPO_URL..." >&2
    if ! download "$REPO_URL/index.json" "$REPO_INDEX"; then
        echo "Warning: failed to fetch alpkg index" >&2
        return 1
    fi
    local count
    count=$(grep -c '"name"' "$REPO_INDEX" 2>/dev/null || echo 0)
    echo "OK ($count alpkg packages)" >&2
}

# ─── .alp extraction / building ─────────────────────────────

extract_alp() {
    local pkg="$1"
    sed -n '/^---control---$/,/^---data---$/p' "$pkg" | grep -v "^---control---$" | grep -v "^---data---$" | base64 -d > control.tar.xz
    awk '/^---data---$/{found=1; next} found' "$pkg" | base64 -d > data.tar.xz
}

build_alp() {
    local name="$1" version="$2" desc="$3" data_dir="$4" out_file="$5"
    mkdir -p "$WORK_DIR/build"
    cd "$WORK_DIR/build" || exit 1
    tar -cJf data.tar.xz -C "$data_dir" .
    cat > metadata.json << EOF
{ "name": "$name", "version": "$version", "description": "$desc", "maintainer": "endermanthecookie@gmail.com" }
EOF
    cat > install.sh << 'INSTALL'
#!/bin/bash
echo "Installing $(grep '"name"' metadata.json | cut -d'"' -f4)..."
echo "Package installed successfully!"
INSTALL
    chmod +x install.sh
    tar -cJf control.tar.xz metadata.json install.sh
    { echo "# alpkg package"; echo "name: $name"; echo "version: $version"; echo ""; echo "---control---"; base64 < control.tar.xz; echo ""; echo "---data---"; base64 < data.tar.xz; } > "$out_file"
    rm -rf "$WORK_DIR/build"
}

# ─── Converters ─────────────────────────────────────────────

deb_to_alp() {
    local deb="$1" out="${2:-$(basename "$deb" .deb).alp}"
    echo "Converting $deb -> $out..." >&2
    mkdir -p "$WORK_DIR/deb-extract"
    dpkg-deb -x "$deb" "$WORK_DIR/deb-extract/data" 2>/dev/null
    local name version desc
    name=$(dpkg-deb -f "$deb" Package 2>/dev/null)
    version=$(dpkg-deb -f "$deb" Version 2>/dev/null)
    desc=$(dpkg-deb -f "$deb" Description 2>/dev/null | head -1)
    [ -z "$name" ] && name=$(basename "$deb" .deb)
    [ -z "$version" ] && version="1.0"
    build_alp "$name" "$version" "$desc" "$WORK_DIR/deb-extract/data" "$out"
    rm -rf "$WORK_DIR/deb-extract"
    echo "Created: $out" >&2
}

rpm_to_alp() {
    local rpm="$1" out="${2:-$(basename "$rpm" .rpm).alp}"
    echo "Converting $rpm -> $out..." >&2
    mkdir -p "$WORK_DIR/rpm-extract/data"
    rpm2cpio "$rpm" 2>/dev/null | cpio -idm -D "$WORK_DIR/rpm-extract/data" 2>/dev/null
    local name version desc
    name=$(rpm -qp --queryformat '%{NAME}' "$rpm" 2>/dev/null)
    version=$(rpm -qp --queryformat '%{VERSION}-%{RELEASE}' "$rpm" 2>/dev/null)
    desc=$(rpm -qp --queryformat '%{SUMMARY}' "$rpm" 2>/dev/null)
    [ -z "$name" ] && name=$(basename "$rpm" .rpm)
    [ -z "$version" ] && version="1.0"
    build_alp "$name" "$version" "$desc" "$WORK_DIR/rpm-extract/data" "$out"
    rm -rf "$WORK_DIR/rpm-extract"
    echo "Created: $out" >&2
}

pkg_to_alp() {
    local pkg="$1" out="${2:-$(basename "$pkg" .pkg.tar.zst).alp}"
    echo "Converting $pkg -> $out..." >&2
    mkdir -p "$WORK_DIR/pkg-extract/data"
    tar -xaf "$pkg" -C "$WORK_DIR/pkg-extract/data" 2>/dev/null
    local name version desc=""
    local pkg_info="$WORK_DIR/pkg-extract/data/.PKGINFO"
    if [ -f "$pkg_info" ]; then
        name=$(grep '^pkgname' "$pkg_info" | cut -d= -f2 | tr -d ' ')
        version=$(grep '^pkgver' "$pkg_info" | cut -d= -f2 | tr -d ' ')
        desc=$(grep '^pkgdesc' "$pkg_info" | cut -d= -f2 | sed 's/^ *//')
    fi
    [ -z "$name" ] && name=$(basename "$pkg" .pkg.tar.zst)
    [ -z "$version" ] && version="1.0"
    rm -f "$WORK_DIR/pkg-extract/data/.PKGINFO" "$WORK_DIR/pkg-extract/data/.INSTALL" \
          "$WORK_DIR/pkg-extract/data/.MTREE" "$WORK_DIR/pkg-extract/data/.BUILDINFO" \
          "$WORK_DIR/pkg-extract/data/.CHANGELOG" 2>/dev/null
    build_alp "$name" "$version" "$desc" "$WORK_DIR/pkg-extract/data" "$out"
    rm -rf "$WORK_DIR/pkg-extract"
    echo "Created: $out" >&2
}

# ─── Source fetchers ────────────────────────────────────────

alpkg_fetch() {
    local pkg_name="$1"
    local cached="$CACHE/$pkg_name.alp"
    local url="$REPO_URL/packages/$pkg_name.alp"
    echo "Trying alpkg repository..." >&2
    if download "$url" "$cached" 2>/dev/null; then
        echo "Found in alpkg repository!" >&2
        echo "$cached"
        return 0
    fi
    return 1
}

apt_fetch() {
    local pkg_name="$1"
    if ! command -v apt-cache >/dev/null 2>&1; then
        echo "APT not available on this system" >&2
        return 1
    fi
    local info
    info=$(apt-cache show "$pkg_name" 2>/dev/null)
    [ -z "$info" ] && return 1
    echo "Found in APT repositories!" >&2
    local version desc
    version=$(echo "$info" | grep '^Version:' | head -1 | cut -d' ' -f2)
    desc=$(echo "$info" | grep '^Description-en:\|^Description:' | head -1 | cut -d' ' -f2-)
    echo "  $pkg_name v$version - $desc" >&2
    echo "Downloading..." >&2

    local apt_tmp="$CACHE/apt"
    mkdir -p "$apt_tmp/partial"
    rm -f "$apt_tmp/"*.deb 2>/dev/null

    DEBIAN_FRONTEND=noninteractive \
    apt-get install --download-only -d -y "$pkg_name" \
        -o Dir::Cache="$apt_tmp" \
        -o Dir::Cache::archives="$apt_tmp" \
        -o Dir::State::status=/var/lib/dpkg/status \
        -o APT::Update::Post-Invoke-Success::="" \
        -o DPkg::Post-Invoke::="" >/dev/null 2>&1

    local deb_file
    deb_file=$(ls "$apt_tmp/"*.deb 2>/dev/null | head -1)
    if [ -z "$deb_file" ] || [ ! -f "$deb_file" ]; then
        echo "Error: failed to download $pkg_name" >&2
        return 1
    fi
    local alp_file="$apt_tmp/$pkg_name.alp"
    deb_to_alp "$deb_file" "$alp_file" >/dev/null 2>&1
    rm -f "$deb_file"
    echo "$alp_file"
}

pacman_fetch() {
    local pkg_name="$1"
    if command -v pacman >/dev/null 2>&1; then
        local info
        info=$(pacman -Si "$pkg_name" 2>/dev/null)
        [ -z "$info" ] && return 1
        echo "Found in Pacman repositories!" >&2
        local version desc
        version=$(echo "$info" | grep '^Version' | cut -d: -f2 | tr -d ' ')
        desc=$(echo "$info" | grep '^Description' | cut -d: -f2- | sed 's/^ //')
        echo "  $pkg_name v$version - $desc" >&2
        echo "Downloading..." >&2
        mkdir -p "$CACHE/pacman"
        pacman -Sw --noconfirm "$pkg_name" --cachedir "$CACHE/pacman" 2>/dev/null
        local pkg_file
        pkg_file=$(ls "$CACHE/pacman/"*.pkg.tar.zst 2>/dev/null | head -1)
        if [ -z "$pkg_file" ] || [ ! -f "$pkg_file" ]; then
            echo "Error: failed to download $pkg_name" >&2
            return 1
        fi
        local alp_file="$CACHE/pacman/$pkg_name.alp"
        pkg_to_alp "$pkg_file" "$alp_file" >/dev/null 2>&1
        rm -f "$pkg_file"
        echo "$alp_file"
        return 0
    fi
    return 1
}

# ─── List helpers ───────────────────────────────────────────

list_alpkg() {
    local name_filter="$1"
    [ ! -f "$REPO_INDEX" ] && fetch_index >/dev/null 2>&1
    [ ! -f "$REPO_INDEX" ] && return

    python3 -c "
import json, sys
with open('$REPO_INDEX') as f:
    data = json.load(f)
nf = '$name_filter'.lower()
for p in data.get('packages', []):
    pn = p.get('name', '').lower()
    if nf and nf not in pn:
        continue
    print(f\"  {p.get('name')} v{p.get('version')} - {p.get('description')}\")
" 2>/dev/null
}

list_apt() {
    local name_filter="$1"
    command -v apt-cache >/dev/null 2>&1 || return

    if [ -n "$name_filter" ]; then
        apt-cache search "$name_filter" 2>/dev/null | while IFS= read -r line; do
            echo "  $line"
        done
    else
        apt-cache dump 2>/dev/null | grep -E '^Package:|^Version:|^Description-en:' | \
        awk '/^Package:/{p=$2} /^Version:/{v=$2} /^Description-en:/{d=$0; sub(/^Description-en: /,""); if(p) print "  "p" v"v" - "$0; p=""; v=""}' | head -50
    fi
}

list_pacman() {
    local name_filter="$1"
    command -v pacman >/dev/null 2>&1 || { echo "  (pacman not available)"; return; }

    if [ -n "$name_filter" ]; then
        pacman -Sl 2>/dev/null | grep -i "$name_filter" | head -30 | while IFS= read -r line; do
            echo "  $line"
        done
    else
        local count
        count=$(pacman -Sl 2>/dev/null | wc -l)
        echo "  ($count total packages)"
        pacman -Sl 2>/dev/null | head -20 | while IFS= read -r line; do
            echo "  $line"
        done
        [ "$count" -gt 20 ] && echo "  ... and $((count - 20)) more (use --name to filter)"
    fi
}

# ─── do_install ──────────────────────────────────────────────

do_install() {
    local pkg_file="$1"
    if [ "$EUID" -ne 0 ]; then
        echo "Error: installation requires root privileges"
        exit 1
    fi
    local name
    name=$(basename "$pkg_file" .alp)
    echo "Installing $name..."
    rm -rf "$WORK_DIR/install"
    mkdir -p "$WORK_DIR/install"
    cd "$WORK_DIR/install" || exit 1
    extract_alp "$pkg_file"
    tar -xJf control.tar.xz 2>/dev/null
    if [ -f metadata.json ]; then
        python3 -c "
import json
d = json.load(open('metadata.json'))
print(f\"Package: {d.get('name', '?')}\")
print(f\"Version: {d.get('version', '?')}\")
print(f\"Description: {d.get('description', '?')}\")
" 2>/dev/null || {
            echo "Package: $(grep -o '"name": *"[^"]*"' metadata.json | cut -d'"' -f4)"
            echo "Version: $(grep -o '"version": *"[^"]*"' metadata.json | cut -d'"' -f4)"
            echo "Description: $(grep -o '"description": *"[^"]*"' metadata.json | cut -d'"' -f4)"
        }
    fi
    if [ -f install.sh ]; then
        chmod +x install.sh
        bash install.sh
    fi
    if [ -f data.tar.xz ]; then
        tar -xJf data.tar.xz -C /
    fi
    mkdir -p "$DB"
    echo "$name" >> "$DB/db"
    echo "Installed: $name"
    rm -rf "$WORK_DIR/install"
}

# ─── Commands ───────────────────────────────────────────────

cmd_convert() {
    local file="$1"
    [ -f "$file" ] || { echo "Error: $file not found"; exit 1; }
    case "$file" in
        *.deb) deb_to_alp "$file" ;;
        *.rpm) rpm_to_alp "$file" ;;
        *.pkg.tar.zst) pkg_to_alp "$file" ;;
        *.alp) echo "Already .alp format: $file" ;;
        *) echo "Unknown format. Supported: .deb, .rpm, .pkg.tar.zst"; exit 1 ;;
    esac
}

cmd_list() {
    local name_filter="" platform_filter=""

    while [ $# -gt 0 ]; do
        case "$1" in
            --name) shift; name_filter="$1" ;;
            --platform) shift; platform_filter="$1" ;;
            *) echo "Unknown option: $1"; exit 1 ;;
        esac
        shift
    done

    if [ -n "$platform_filter" ] && [ "$platform_filter" != "alpkg" ] && \
       [ "$platform_filter" != "apt" ] && [ "$platform_filter" != "pacman" ]; then
        echo "Error: --platform must be: alpkg, apt, or pacman"
        exit 1
    fi

    # Installed
    echo "=== Installed ==="
    if [ -f "$DB/db" ] && [ -s "$DB/db" ]; then
        if [ -n "$name_filter" ]; then
            grep -i "$name_filter" "$DB/db" | while IFS= read -r pkg; do
                echo "  $pkg"
            done
        else
            sed 's/^/  /' "$DB/db"
        fi
    else
        echo "  (none)"
    fi
    echo ""

    # alpkg
    if [ -z "$platform_filter" ] || [ "$platform_filter" = "alpkg" ]; then
        echo "=== alpkg ($REPO_URL) ==="
        local alpkg_count
        alpkg_count=$(list_alpkg "$name_filter")
        if [ -n "$alpkg_count" ]; then
            echo "$alpkg_count"
        else
            echo "  (none)"
        fi
        echo ""
    fi

    # APT
    if [ -z "$platform_filter" ] || [ "$platform_filter" = "apt" ]; then
        echo "=== APT ==="
        local apt_count
        apt_count=$(list_apt "$name_filter")
        if [ -n "$apt_count" ]; then
            echo "$apt_count"
        else
            echo "  (none or not available)"
        fi
        echo ""
    fi

    # Pacman
    if [ -z "$platform_filter" ] || [ "$platform_filter" = "pacman" ]; then
        echo "=== Pacman ==="
        local pac_count
        pac_count=$(list_pacman "$name_filter")
        if [ -n "$pac_count" ]; then
            echo "$pac_count"
        else
            echo "  (none or not available)"
        fi
        echo ""
    fi
}

cmd_install() {
    local target="" mode=""
    local alpkg_avail=1 apt_avail=1 pacman_avail=1

    while [ $# -gt 0 ]; do
        case "$1" in
            --alpkg) mode="alpkg" ;;
            --apt) mode="apt" ;;
            --pacman) mode="pacman" ;;
            --*) echo "Unknown option: $1"; exit 1 ;;
            *) target="$1" ;;
        esac
        shift
    done

    [ -z "$target" ] && { echo "Usage: alpkg install <pkg> [--alpkg|--apt|--pacman]"; exit 1; }

    if [ -f "$target" ]; then
        case "$target" in
            *.alp) do_install "$target"; return ;;
            *.deb)
                mkdir -p "$CACHE/convert"
                local conv="$CACHE/convert/$(basename "$target" .deb).alp"
                deb_to_alp "$target" "$conv" || exit 1
                do_install "$conv"; return ;;
            *.rpm)
                mkdir -p "$CACHE/convert"
                local conv="$CACHE/convert/$(basename "$target" .rpm).alp"
                rpm_to_alp "$target" "$conv" || exit 1
                do_install "$conv"; return ;;
            *.pkg.tar.zst)
                mkdir -p "$CACHE/convert"
                local conv="$CACHE/convert/$(basename "$target" .pkg.tar.zst).alp"
                pkg_to_alp "$target" "$conv" || exit 1
                do_install "$conv"; return ;;
        esac
    fi

    if [ "$EUID" -ne 0 ]; then
        echo "Error: remote install requires root privileges"
        exit 1
    fi

    command -v apt-cache >/dev/null 2>&1 || apt_avail=0
    command -v pacman >/dev/null 2>&1 || pacman_avail=0

    local sources=()
    local source_funcs=()
    if [ "$alpkg_avail" -eq 1 ]; then sources+=("alpkg"); source_funcs+=("alpkg_fetch"); fi
    if [ "$apt_avail" -eq 1 ]; then sources+=("apt"); source_funcs+=("apt_fetch"); fi
    if [ "$pacman_avail" -eq 1 ]; then sources+=("pacman"); source_funcs+=("pacman_fetch"); fi

    if [ -n "$mode" ]; then
        case "$mode" in
            alpkg) pkg_file=$(alpkg_fetch "$target") ;;
            apt)   pkg_file=$(apt_fetch "$target") ;;
            pacman) pkg_file=$(pacman_fetch "$target") ;;
        esac
        if [ -z "$pkg_file" ]; then
            echo "Error: $mode: package '$target' not found"
            exit 1
        fi
        do_install "$pkg_file"
        return
    fi

    local failed=()
    while [ ${#sources[@]} -gt 0 ]; do
        local src="${sources[0]}"
        local func="${source_funcs[0]}"
        echo "--- Trying $src ---"
        pkg_file=$($func "$target")
        if [ -n "$pkg_file" ]; then
            do_install "$pkg_file"
            return
        fi
        echo "$src: package '$target' not found"
        failed+=("$src")
        sources=("${sources[@]:1}")
        source_funcs=("${source_funcs[@]:1}")

        [ ${#sources[@]} -eq 0 ] && break

        echo ""
        echo "Which source should I try next?"
        for i in "${!sources[@]}"; do
            echo "  $((i+1))) ${sources[$i]}"
        done
        read -r -p "Choice [1-${#sources[@]}]: " choice
        if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "${#sources[@]}" ]; then
            local idx=$((choice-1))
            local chosen_src="${sources[$idx]}"
            local chosen_func="${source_funcs[$idx]}"
            sources=("$chosen_src" "${sources[@]:0:idx}" "${sources[@]:idx+1}")
            source_funcs=("$chosen_func" "${source_funcs[@]:0:idx}" "${source_funcs[@]:idx+1}")
        else
            echo "Invalid choice, trying next in order"
        fi
    done

    echo ""
    echo "Error: '$target' not found in any available source"
    echo "Tried: ${failed[*]}"
    exit 1
}

cmd_remove() {
    if [ "$EUID" -ne 0 ]; then echo "Error: removal requires root privileges"; exit 1; fi
    local name="$2"
    echo "Removing $name..."
    [ -f "/usr/bin/$name" ] && rm -f "/usr/bin/$name" && echo "Removed: /usr/bin/$name"
    [ -f "/usr/local/bin/$name" ] && rm -f "/usr/local/bin/$name" && echo "Removed: /usr/local/bin/$name"
    [ -f "$DB/db" ] && sed -i "/^$name$/d" "$DB/db" 2>/dev/null
    echo "Removed: $name"
}

cmd_info() {
    local target="$1"
    if [ -f "$target" ] && [[ "$target" == *.alp ]]; then
        cd /tmp || exit 1; rm -rf alpkg-info; mkdir alpkg-info; cd alpkg-info || exit 1
        sed -n '/^---control---$/,/^---data---$/p' "$target" | grep -v "^---control---$" | grep -v "^---data---$" | base64 -d > control.tar.xz
        tar -xJf control.tar.xz 2>/dev/null
        [ -f metadata.json ] && cat metadata.json
        rm -rf /tmp/alpkg-info
    elif [ -f "$REPO_INDEX" ]; then
        python3 -c "
import json, sys
with open('$REPO_INDEX') as f:
    data = json.load(f)
for p in data.get('packages', []):
    if p.get('name') == '$target':
        print(json.dumps(p, indent=2))
        sys.exit(0)
print('Package not found')
" 2>/dev/null
    else
        echo "Error: no index cached. Run 'alpkg update' first"; exit 1
    fi
}

cmd_search() {
    local query="$1"

    echo "=== alpkg ($REPO_URL) ==="
    list_alpkg "$query"
    echo ""

    echo "=== APT ==="
    if command -v apt-cache >/dev/null 2>&1; then
        apt-cache search "$query" 2>/dev/null | head -20
    else
        echo "  (not available)"
    fi
    echo ""

    echo "=== Pacman ==="
    if command -v pacman >/dev/null 2>&1; then
        pacman -Sl 2>/dev/null | grep -i "$query" | head -20
    else
        echo "  (not available)"
    fi
}

cmd_update() {
    if [ "$EUID" -ne 0 ]; then echo "Error: update requires root privileges"; exit 1; fi
    fetch_index
    command -v apt-get >/dev/null 2>&1 && { echo "Updating APT cache..."; apt-get update 2>/dev/null | tail -1; }
    echo "Done"
}

cmd_repo() {
    local action="$2"
    if [ "$action" = "set" ]; then
        local new_url="$3"
        [ -z "$new_url" ] && { echo "Usage: sudo alpkg repo set <url>"; exit 1; }
        mkdir -p "$(dirname "$CONF")"
        cat > "$CONF" << EOF
# alpkg configuration
# Maintainer: endermanthecookie@gmail.com
# Repository: https://packages-aaron-linux.vercel.app
# To change source: sudo alpkg repo set <url>
REPO_URL="$new_url"
EOF
        echo "Repository set to: $new_url"
    else
        echo "Current alpkg repository: $REPO_URL"
        echo "Config file: $CONF"
        echo ""
        echo "To change: sudo alpkg repo set <url>"
        echo "Default:   https://packages-aaron-linux.vercel.app"
        command -v apt-cache >/dev/null 2>&1 && echo "APT:     available"
        command -v pacman >/dev/null 2>&1 && echo "Pacman:  available"
    fi
}

if [ $# -lt 1 ]; then help; exit 1; fi

mkdir -p "$DB" "$PKG_DIR" "$CACHE"

if [ ! -f "$BOOTSTRAP_MARKER" ] && [ "$1" != "bootstrap" ]; then
    echo "alpkg: first run detected. Running bootstrap..."
    bootstrap
    echo "alpkg: bootstrap complete."
fi

case "$1" in
    bootstrap) bootstrap ;;
    install) shift; cmd_install "$@" ;;
    remove) cmd_remove "$@" ;;
    list) shift; cmd_list "$@" ;;
    info) cmd_info "$2" ;;
    search) cmd_search "$2" ;;
    update) cmd_update ;;
    repo) cmd_repo "$@" ;;
    convert) cmd_convert "$2" ;;
    *) help ;;
esac
