#!/usr/bin/env bash
# Copyright (c) 2016-2024 The Hush developers
# Copyright (c) 2024-2026 The DragonX developers
# Distributed under the GPLv3 software license, see the accompanying
# file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html

set -eu -o pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
RELEASE_DIR="$SCRIPT_DIR/release"

# Derive the release version from configure.ac instead of hardcoding it here.
# A stale literal names the release directories after the wrong version while the
# binaries inside report the real one: this said 1.0.3 while the tree was already
# 1.1.0, so `./build.sh --all-release` would have produced
# release/dragonx-1.0.3-<platform>/ full of binaries announcing 1.1.0.
# Mirrors configure.ac's _CLIENT_VERSION_SUFFIX m4 exactly:
#   build < 25 -> beta(build+1)   build < 50 -> rc(build-24)
#   build == 50 -> plain release  build > 50 -> point release (build-50)
_acdef() { sed -n "s/^define(_CLIENT_VERSION_$1, *\([0-9]\{1,\}\))/\1/p" "$SCRIPT_DIR/configure.ac"; }
_V_MAJOR="$(_acdef MAJOR)"
_V_MINOR="$(_acdef MINOR)"
_V_REVISION="$(_acdef REVISION)"
_V_BUILD="$(_acdef BUILD)"
if [ -z "$_V_MAJOR" ] || [ -z "$_V_MINOR" ] || [ -z "$_V_REVISION" ] || [ -z "$_V_BUILD" ]; then
    echo "ERROR: could not read the version from $SCRIPT_DIR/configure.ac" >&2
    echo "       refusing to build a release whose directory name would be wrong." >&2
    exit 1
fi
if   [ "$_V_BUILD" -lt 25 ]; then _V_SUFFIX="$_V_REVISION-beta$((_V_BUILD + 1))"
elif [ "$_V_BUILD" -lt 50 ]; then _V_SUFFIX="$_V_REVISION-rc$((_V_BUILD - 24))"
elif [ "$_V_BUILD" -eq 50 ]; then _V_SUFFIX="$_V_REVISION"
else                              _V_SUFFIX="$_V_REVISION-$((_V_BUILD - 50))"
fi
VERSION="$_V_MAJOR.$_V_MINOR.$_V_SUFFIX"

# Parse release flags
BUILD_LINUX_RELEASE=0
BUILD_WIN_RELEASE=0
BUILD_MAC_RELEASE=0
BUILD_LINUX_COMPAT=0
REMAINING_ARGS=()

for arg in "$@"; do
    case "$arg" in
        --linux-release)
            BUILD_LINUX_RELEASE=1
            ;;
        --linux-compat)
            BUILD_LINUX_COMPAT=1
            ;;
        --win-release)
            BUILD_WIN_RELEASE=1
            ;;
        --mac-release)
            BUILD_MAC_RELEASE=1
            ;;
        --all-release)
            BUILD_LINUX_RELEASE=1
            BUILD_WIN_RELEASE=1
            BUILD_MAC_RELEASE=1
            ;;
        *)
            REMAINING_ARGS+=("$arg")
            ;;
    esac
done

# Clean artifacts that may conflict between platform builds
clean_for_platform() {
    local platform="$1"
    echo "Cleaning build artifacts for $platform build..."
    
    # Use make clean if Makefile exists (safer than manual deletion)
    if [ -f src/Makefile ]; then
        make -C src clean 2>/dev/null || true
    fi
    
    # Remove final binaries
    if [ -d src ]; then
        rm -f src/dragonxd src/dragonx-cli src/dragonx-tx 2>/dev/null || true
        rm -f src/dragonxd.exe src/dragonx-cli.exe src/dragonx-tx.exe 2>/dev/null || true
        rm -f src/hushd src/hush-cli src/hush-tx 2>/dev/null || true
        rm -f src/hushd.exe src/hush-cli.exe src/hush-tx.exe 2>/dev/null || true
    fi
    
    # Clean RandomX build for cross-platform compatibility
    rm -rf src/RandomX/build 2>/dev/null || true
    
    # Clean cryptoconditions
    rm -rf src/cc/*.o src/cc/*.a 2>/dev/null || true
    
    # Clean config cache (forces reconfigure for cross-platform)
    rm -f config.status config.log 2>/dev/null || true
    
    echo "Clean complete for $platform"
}

# Package release for a platform
package_release() {
    local platform="$1"
    local release_subdir="$RELEASE_DIR/dragonx-$VERSION-$platform"
    
    echo "Packaging release for $platform..."
    mkdir -p "$release_subdir"
    
    # Copy bootstrap script (platform-appropriate)
    if [ "$platform" = "win64" ]; then
        cp "$SCRIPT_DIR/util/bootstrap-dragonx.bat" "$release_subdir/"
    else
        cp "$SCRIPT_DIR/util/bootstrap-dragonx.sh" "$release_subdir/"
    fi
    
    # Copy common files
    cp "$SCRIPT_DIR/contrib/asmap/asmap.dat" "$release_subdir/" 2>/dev/null || true
    cp "$SCRIPT_DIR/sapling-output.params" "$release_subdir/" 2>/dev/null || true
    cp "$SCRIPT_DIR/sapling-spend.params" "$release_subdir/" 2>/dev/null || true
    
    case "$platform" in
        linux-amd64)
            cp "$SCRIPT_DIR/src/dragonxd" "$release_subdir/"
            cp "$SCRIPT_DIR/src/dragonx-cli" "$release_subdir/"
            cp "$SCRIPT_DIR/src/dragonx-tx" "$release_subdir/"
            strip "$release_subdir/dragonxd" "$release_subdir/dragonx-cli" "$release_subdir/dragonx-tx"
            ;;
        win64)
            cp "$SCRIPT_DIR/src/dragonxd.exe" "$release_subdir/"
            cp "$SCRIPT_DIR/src/dragonx-cli.exe" "$release_subdir/"
            cp "$SCRIPT_DIR/src/dragonx-tx.exe" "$release_subdir/"
            x86_64-w64-mingw32-strip "$release_subdir/"*.exe 2>/dev/null || strip "$release_subdir/"*.exe 2>/dev/null || true
            ;;
        macos)
            cp "$SCRIPT_DIR/src/dragonxd" "$release_subdir/"
            cp "$SCRIPT_DIR/src/dragonx-cli" "$release_subdir/"
            cp "$SCRIPT_DIR/src/dragonx-tx" "$release_subdir/"
            strip "$release_subdir/dragonxd" "$release_subdir/dragonx-cli" "$release_subdir/dragonx-tx" 2>/dev/null || true
            ;;
    esac
    
    echo "Release packaged: $release_subdir"
    ls -la "$release_subdir"
}

# Handle release builds
if [ $BUILD_LINUX_COMPAT -eq 1 ] || [ $BUILD_LINUX_RELEASE -eq 1 ] || [ $BUILD_WIN_RELEASE -eq 1 ] || [ $BUILD_MAC_RELEASE -eq 1 ]; then
    mkdir -p "$RELEASE_DIR"

    if [ $BUILD_LINUX_COMPAT -eq 1 ]; then
        echo "=== Building Linux compat release (Ubuntu 20.04 via Docker) ==="
        if ! command -v docker &>/dev/null; then
            echo "Error: docker is required for --linux-compat builds"
            exit 1
        fi

        # Use sudo for docker if the user isn't in the docker group
        DOCKER_CMD="docker"
        if ! docker info &>/dev/null 2>&1; then
            echo "Note: Using sudo for docker (add yourself to the docker group to avoid this)"
            DOCKER_CMD="sudo docker"
        fi

        DOCKER_IMAGE="dragonx-compat-builder"
        COMPAT_PLATFORM="linux-amd64-ubuntu2004"
        COMPAT_RELEASE_DIR="$RELEASE_DIR/dragonx-$VERSION-$COMPAT_PLATFORM"

        echo "Building Docker image (Ubuntu 20.04 base)..."
        # .dockerignore excludes .git, so genbuild.sh inside the container cannot
        # derive the version and would stamp the binaries "-unk". Compute it on the
        # host, mirroring util/genbuild.sh exactly, and pass it in via --build-arg.
        # NB: build.sh runs under `set -eu -o pipefail`, so every git call here must be
        # non-fatal -- a source tarball, a machine without git, or a branch whose only
        # reachable tags are lightweight (v1.0.1-v1.0.3) would otherwise abort the build.
        git diff >/dev/null 2>&1 || true   # refresh index: touched-but-unmodified are not dirty
        COMPAT_BUILD_DESC=""
        COMPAT_RAWDESC=$(git describe --abbrev=0 2>/dev/null || true)
        if [ -n "$COMPAT_RAWDESC" ] \
           && [ "$(git rev-parse HEAD 2>/dev/null)" = "$(git rev-list -1 "$COMPAT_RAWDESC" 2>/dev/null)" ] \
           && git diff-index --quiet HEAD -- 2>/dev/null; then
            COMPAT_BUILD_DESC="$COMPAT_RAWDESC"
        else
            COMPAT_SUFFIX=$(git rev-parse --short HEAD 2>/dev/null || true)
            if [ -n "$COMPAT_SUFFIX" ]; then
                git diff-index --quiet HEAD -- 2>/dev/null || COMPAT_SUFFIX="$COMPAT_SUFFIX-dirty"
                COMPAT_BUILD_DESC="v$VERSION-$COMPAT_SUFFIX"
            fi
        fi
        if [ -n "$COMPAT_BUILD_DESC" ]; then
            echo "Stamping container build as: $COMPAT_BUILD_DESC"
        else
            echo "Warning: no usable git metadata; container binaries will be stamped -unk"
        fi
        $DOCKER_CMD build -f Dockerfile.compat \
            --build-arg BUILD_DESC="$COMPAT_BUILD_DESC" \
            -t "$DOCKER_IMAGE" .

        echo "Extracting binaries from Docker image..."
        CONTAINER_ID=$($DOCKER_CMD create "$DOCKER_IMAGE")
        mkdir -p "$COMPAT_RELEASE_DIR"

        for bin in dragonxd dragonx-cli dragonx-tx; do
            $DOCKER_CMD cp "$CONTAINER_ID:/build/src/$bin" "$COMPAT_RELEASE_DIR/$bin"
        done
        $DOCKER_CMD rm "$CONTAINER_ID" >/dev/null

        # Fix ownership (docker cp creates root-owned files)
        # Binaries are already stripped inside the Docker container
        if [ "$(stat -c '%U' "$COMPAT_RELEASE_DIR/dragonxd")" = "root" ]; then
            sudo chown "$(id -u):$(id -g)" "$COMPAT_RELEASE_DIR"/dragonx*
        fi

        # Copy common files
        cp "$SCRIPT_DIR/util/bootstrap-dragonx.sh" "$COMPAT_RELEASE_DIR/"
        cp "$SCRIPT_DIR/contrib/asmap/asmap.dat" "$COMPAT_RELEASE_DIR/" 2>/dev/null || true
        cp "$SCRIPT_DIR/sapling-output.params" "$COMPAT_RELEASE_DIR/" 2>/dev/null || true
        cp "$SCRIPT_DIR/sapling-spend.params" "$COMPAT_RELEASE_DIR/" 2>/dev/null || true

        echo "Compat release packaged: $COMPAT_RELEASE_DIR"
        ls -la "$COMPAT_RELEASE_DIR"

        # Show glibc version requirement
        echo ""
        echo "Binary compatibility info:"
        objdump -T "$COMPAT_RELEASE_DIR/dragonxd" | grep -oP 'GLIBC_\d+\.\d+' | sort -uV | tail -1 && echo "(max GLIBC version required)"
    fi
    
    if [ $BUILD_LINUX_RELEASE -eq 1 ]; then
        echo "=== Building Linux release ==="
        clean_for_platform linux
        ./util/build.sh --disable-tests ${REMAINING_ARGS[@]+"${REMAINING_ARGS[@]}"}
        package_release linux-amd64
    fi
    
    if [ $BUILD_WIN_RELEASE -eq 1 ]; then
        echo "=== Building Windows release ==="
        clean_for_platform windows
        ./util/build-win.sh --disable-tests ${REMAINING_ARGS[@]+"${REMAINING_ARGS[@]}"}
        package_release win64
    fi
    
    if [ $BUILD_MAC_RELEASE -eq 1 ]; then
        echo "=== Building macOS release ==="
        clean_for_platform macos
        ./util/build-mac.sh --disable-tests ${REMAINING_ARGS[@]+"${REMAINING_ARGS[@]}"}
        package_release macos
    fi
    
    echo ""
    echo "=== Release builds complete ==="
    ls -la "$RELEASE_DIR"/
    exit 0
fi

# Standard build (auto-detect OS)
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
    ./util/build.sh --disable-tests ${REMAINING_ARGS[@]+"${REMAINING_ARGS[@]}"}
elif [[ "$OSTYPE" == "darwin"* ]]; then
    ./util/build-mac.sh --disable-tests ${REMAINING_ARGS[@]+"${REMAINING_ARGS[@]}"}
elif [[ "$OSTYPE" == "msys"* ]]; then
    ./util/build-win.sh --disable-tests ${REMAINING_ARGS[@]+"${REMAINING_ARGS[@]}"}
else
    echo "Unable to detect your OS. What are you using?"
fi
