#!/bin/bash
set -e

if [ $# -ne 1 ]; then
    echo "Usage: $0 <version>"
    echo "Example: $0 0.7.0"
    echo ""
    echo "Use 'uscan' to check for new upstream versions first."
    exit 1
fi

VERSION="$1"
SCRIPT_DIR="$(dirname "$(realpath "$0")")"
TARGET="$(dirname "$(dirname "$SCRIPT_DIR")")"
WORKDIR="$TARGET/coreutils-repack"

echo "Repacking coreutils version $VERSION"
echo "Target directory: $TARGET"
echo "Work directory: $WORKDIR"

# Check if running interactively
if [ -t 0 ]; then
    echo "Please update the version in debian/changelog"
    read -p "Press enter when done..."
else
    echo "Running non-interactively - assuming changelog is up to date"
fi

# Clone tagged source first
echo "Cloning coreutils source at version $VERSION..."
rm -rf "$WORKDIR"
if ! git clone git@github.com:uutils/coreutils.git -b "$VERSION" "$WORKDIR"; then
    echo "Error: Failed to clone coreutils at version $VERSION"
    exit 1
fi

# Clone l10n repo
echo "Cloning coreutils-l10n at version $VERSION..."
rm -rf /tmp/coreutils-l10n
if ! git clone https://github.com/uutils/coreutils-l10n.git -b "$VERSION" /tmp/coreutils-l10n; then
    echo "Warning: Failed to clone coreutils-l10n at version $VERSION, trying main branch..."
    if ! git clone https://github.com/uutils/coreutils-l10n.git /tmp/coreutils-l10n; then
        echo "Error: Failed to clone coreutils-l10n repo"
        exit 1
    fi
fi

cd "$WORKDIR"

# Add localized versions (only locale files, not overwriting structure)
echo "Adding localized files..."
if [ -d "/tmp/coreutils-l10n/src/uu" ]; then
    for util_dir in /tmp/coreutils-l10n/src/uu/*/; do
        util_name=$(basename "$util_dir")
        if [ -d "./src/uu/$util_name" ]; then
            cp -R "$util_dir"* "./src/uu/$util_name/" 2>/dev/null || true
        fi
    done
fi
if [ -d "/tmp/coreutils-l10n/src/uucore" ]; then
    cp -R /tmp/coreutils-l10n/src/uucore/* ./src/uucore/ 2>/dev/null || true
fi

# Download tldr pages
echo "Downloading tldr pages..."
mkdir -p docs
if ! curl -L https://github.com/tldr-pages/tldr/releases/latest/download/tldr.zip -o docs/tldr.zip; then
    echo "Warning: Failed to download tldr.zip, continuing without it"
    rm -f docs/tldr.zip
fi

# Vendor dependencies
echo "Vendoring Cargo dependencies..."
if ! cargo vendor; then
    echo "Error: Failed to vendor cargo dependencies"
    exit 1
fi

# Copy debian directory to build directory
echo "Copying debian directory to build directory..."
if ! cp -R "$SCRIPT_DIR" "$WORKDIR/debian"; then
    echo "Error: Failed to copy debian directory"
    exit 1
fi

# Clean up
rm -rf "$WORKDIR/.pc/"

# Force clean before creating tarball
echo "Running debian/rules clean..."
debian/rules clean || true

# Remove problematic symlinks that point outside the source tree
echo "Removing problematic symlinks..."
find "$WORKDIR/debian/cargo_registry" -type l -delete 2>/dev/null || true

cd "$TARGET"

# Remove any pre-existing orig tarballs for this version to avoid
# dpkg-source complaining about multiple orig.tar files (e.g. .gz and .xz).
echo "Removing any pre-existing orig tarballs for version $VERSION..."
rm -f "rust-coreutils_${VERSION}.orig.tar."{gz,bz2,xz,lzma}

# Strip .git metadata so gbp import-orig accepts the tarball.
echo "Removing .git metadata from source tree..."
find "$WORKDIR" -depth -name .git -exec rm -rf {} +

echo "Creating source tarball..."
if ! tar Jcvf "rust-coreutils_${VERSION}.orig.tar.xz" coreutils-repack/; then
    echo "Error: Failed to create source tarball"
    exit 1
fi

echo "Building source package..."
if ! dpkg-source -b -i coreutils-repack; then
    # dpkg-source applies the quilt series with ZERO fuzz (it runs
    # `patch -F 0`), so any patch whose context drifted against the new
    # upstream is rejected here even though a plain `quilt push` (which
    # tolerates fuzz) would have accepted it. This is the usual reason a
    # new-upstream repack fails: one or more debian/patches need rebasing.
    #
    # We deliberately do NOT auto-`quilt refresh` the patches: refreshing a
    # force-applied patch silently DROPS the hunks that failed to apply,
    # producing a patch that builds but no longer does what it was written
    # to do. Instead we report exactly which patches are broken and print a
    # step-by-step recipe to rebase them by hand.
    echo ""
    echo "❌ dpkg-source failed: one or more debian/patches no longer apply"
    echo "   cleanly against upstream $VERSION (dpkg-source allows no fuzz)."
    echo ""

    # Detect which patches are broken by replaying the series in the work
    # tree. Cleanly-applying patches stay pushed so later ones stack on the
    # correct base; a broken patch is force-applied just to expose its .rej
    # files, which we list and then clean up.
    cd "$WORKDIR"
    export QUILT_PATCHES=debian/patches
    quilt pop -af >/dev/null 2>&1 || true
    rm -rf .pc
    echo "Patches that need rebasing:"
    broken_patches=""
    for p in $(quilt series); do
        if quilt push "$p" >/dev/null 2>&1; then
            continue
        fi
        broken_patches="$broken_patches $p"
        echo "  ✗ $p"
        quilt push -f "$p" >/dev/null 2>&1 || true
        for r in $(find . -name '*.rej' 2>/dev/null); do
            echo "        rejected hunk(s) in: ${r#./}"
        done
        find . -name '*.rej' -delete 2>/dev/null || true
    done
    quilt pop -af >/dev/null 2>&1 || true
    rm -rf .pc
    cd "$TARGET"

    # The work tree is intentionally left in place (it is only removed on a
    # successful run) so the patches can be rebased without re-vendoring.
    cat <<EOF

────────────────────────────────────────────────────────────────────────
How to fix it (rebase the broken patch(es) against upstream $VERSION)
────────────────────────────────────────────────────────────────────────
The unpacked, vendored work tree has been kept at:
    $WORKDIR

For EACH patch listed above, rebase it there:

    cd "$WORKDIR"
    export QUILT_PATCHES=debian/patches

    # 1. Push patches until the broken one. 'quilt push -f <patch>'
    #    force-applies it and writes <file>.rej for the hunks that did
    #    not apply.
    quilt push -f <broken-patch>

    # 2. Hand-merge each <file>.rej into <file>, then delete the .rej.
    #    A patch that only *appends* a block usually just needs its hunk
    #    re-anchored on the new surrounding lines (check the upstream diff
    #    with: git -C "$WORKDIR" log --oneline   /   git diff).

    # 3. Record the rebased patch at zero fuzz (what dpkg-source needs):
    quilt refresh
    find . -name '*.rej' -delete

    # 4. Confirm the WHOLE series still applies cleanly, then unwind:
    quilt push -a && quilt pop -a
    rm -rf .pc

    # 5. Copy the rebased patch(es) back into the packaging repo so the
    #    fix is permanent (next repack just works):
    cp "$WORKDIR"/debian/patches/<patch> "$SCRIPT_DIR/patches/"

    # 6. Rebuild the source package (the .orig tarball already exists, so
    #    this is fast):
    cd "$TARGET"
    dpkg-source -b -i coreutils-repack

Then commit the refreshed patches under debian/patches/ and, if you like,
re-run this script for a clean end-to-end repack.
────────────────────────────────────────────────────────────────────────
EOF
    exit 1
fi

echo ""
echo "✅ Repack complete!"
echo "Created: rust-coreutils_${VERSION}.orig.tar.xz"
echo "Created: rust-coreutils_${VERSION}-1.dsc"
echo "Created: rust-coreutils_${VERSION}-1.debian.tar.xz"

# Cleanup
rm -rf "$WORKDIR"
