#!/bin/bash

# Build fully static MUSL binaries for Ginxsom using Alpine Docker
# Produces truly portable binaries with zero runtime dependencies

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BUILD_DIR="$SCRIPT_DIR/build"
DOCKERFILE="$SCRIPT_DIR/Dockerfile.alpine-musl"

# Parse command line arguments
DEBUG_BUILD=false
TARGET_ARCH=""

while [[ $# -gt 0 ]]; do
    case "$1" in
        --debug)
            DEBUG_BUILD=true
            shift
            ;;
        --arch)
            if [[ -z "$2" ]]; then
                echo "ERROR: --arch requires a value"
                echo "Usage: $0 [--debug] [--arch <arm64|armv7|x86_64>]"
                exit 1
            fi
            case "$2" in
                arm64|armv7|x86_64)
                    TARGET_ARCH="$2"
                    ;;
                *)
                    echo "ERROR: Unsupported architecture '$2'"
                    echo "Supported values: arm64, armv7, x86_64"
                    exit 1
                esac
            shift 2
            ;;
        *)
            echo "ERROR: Unknown argument '$1'"
            echo "Usage: $0 [--debug] [--arch <arm64|armv7|x86_64>]"
            exit 1
            ;;
    esac
done

if [ "$DEBUG_BUILD" = true ]; then
    echo "=========================================="
    echo "Ginxsom MUSL Static Binary Builder (DEBUG MODE)"
    echo "=========================================="
else
    echo "=========================================="
    echo "Ginxsom MUSL Static Binary Builder (PRODUCTION MODE)"
    echo "=========================================="
fi
echo "Project directory: $SCRIPT_DIR"
echo "Build directory: $BUILD_DIR"
echo "Debug build: $DEBUG_BUILD"
if [[ -n "$TARGET_ARCH" ]]; then
    echo "Requested target architecture: $TARGET_ARCH"
fi
echo ""

# Create build directory
mkdir -p "$BUILD_DIR"

# Check if Docker is available
if ! command -v docker &> /dev/null; then
    echo "ERROR: Docker is not installed or not in PATH"
    echo ""
    echo "Docker is required to build MUSL static binaries."
    echo "Please install Docker:"
    echo "  - Ubuntu/Debian: sudo apt install docker.io"
    echo "  - Or visit: https://docs.docker.com/engine/install/"
    echo ""
    exit 1
fi

# Check if Docker daemon is running
if ! docker info &> /dev/null; then
    echo "ERROR: Docker daemon is not running or user not in docker group"
    echo ""
    echo "Please start Docker and ensure you're in the docker group:"
    echo "  - sudo systemctl start docker"
    echo "  - sudo usermod -aG docker $USER && newgrp docker"
    echo "  - Or start Docker Desktop"
    echo ""
    exit 1
fi

DOCKER_CMD="docker"

echo "✓ Docker is available and running"
echo ""

# Detect host architecture
ARCH=$(uname -m)
case "$ARCH" in
    x86_64)
        HOST_ARCH="x86_64"
        ;;
    aarch64|arm64)
        HOST_ARCH="arm64"
        ;;
    armv7l|armv7)
        HOST_ARCH="armv7"
        ;;
    *)
        HOST_ARCH="unknown"
        ;;
esac

# Resolve target architecture
if [[ -n "$TARGET_ARCH" ]]; then
    ARCH="$TARGET_ARCH"
fi

case "$ARCH" in
    x86_64)
        PLATFORM="linux/amd64"
        OUTPUT_NAME="ginxsom-fcgi_static_x86_64"
        ;;
    aarch64|arm64)
        ARCH="arm64"
        PLATFORM="linux/arm64"
        OUTPUT_NAME="ginxsom-fcgi_static_arm64"
        ;;
    armv7l|armv7)
        ARCH="armv7"
        PLATFORM="linux/arm/v7"
        OUTPUT_NAME="ginxsom-fcgi_static_armv7"
        ;;
    *)
        echo "WARNING: Unknown architecture: $ARCH"
        echo "Defaulting to linux/amd64"
        PLATFORM="linux/amd64"
        OUTPUT_NAME="ginxsom-fcgi_static_${ARCH}"
        ;;
esac

# When cross-building, ensure buildx exists and warn about QEMU/binfmt setup
if [[ "$HOST_ARCH" != "unknown" && "$ARCH" != "$HOST_ARCH" ]]; then
    echo "NOTE: Cross-building from host '$HOST_ARCH' to target '$ARCH'."
    echo "      Docker QEMU/binfmt support is required for this to work."
    if ! docker buildx version >/dev/null 2>&1; then
        echo "ERROR: docker buildx is required for cross-architecture builds but is not available."
        echo "Install/enable buildx and binfmt support, then retry."
        exit 1
    fi
    echo "✓ docker buildx is available for cross-architecture build"
    echo ""
fi

# Append _debug suffix to output name for debug builds so production binary is never overwritten
if [ "$DEBUG_BUILD" = true ]; then
    OUTPUT_NAME="${OUTPUT_NAME}_debug"
fi

echo "Building for platform: $PLATFORM"
echo "Output binary: $OUTPUT_NAME"
echo ""

# Check if Alpine base image is cached
echo "Checking for cached Alpine Docker image..."
if ! docker images alpine:3.19 --format "{{.Repository}}:{{.Tag}}" | grep -q "alpine:3.19"; then
    echo "⚠ Alpine 3.19 image not found in cache"
    echo "Attempting to pull Alpine 3.19 image..."
    if ! docker pull alpine:3.19; then
        echo ""
        echo "ERROR: Failed to pull Alpine 3.19 image"
        echo "This is required for the static build."
        echo ""
        echo "Possible solutions:"
        echo "  1. Check your internet connection"
        echo "  2. Try again later (Docker Hub may be temporarily unavailable)"
        echo "  3. If you have IPv6 issues, disable IPv6 for Docker"
        echo ""
        exit 1
    fi
    echo "✓ Alpine 3.19 image pulled successfully"
else
    echo "✓ Alpine 3.19 image found in cache"
fi
echo ""

# Build the Docker image
echo "=========================================="
echo "Step 1: Building Alpine Docker image"
echo "=========================================="
echo "This will:"
echo "  - Use Alpine Linux (native MUSL)"
echo "  - Build all dependencies statically"
echo "  - Compile Ginxsom with full static linking"
echo ""

$DOCKER_CMD build \
    --platform "$PLATFORM" \
    --build-arg DEBUG_BUILD=$DEBUG_BUILD \
    -f "$DOCKERFILE" \
    -t ginxsom-musl-builder:latest \
    --progress=plain \
    . || {
        echo ""
        echo "ERROR: Docker build failed"
        echo "Check the output above for details"
        exit 1
    }

echo ""
echo "✓ Docker image built successfully"
echo ""

# Extract the binary from the container
echo "=========================================="
echo "Step 2: Extracting static binary"
echo "=========================================="

# Build the builder stage to extract the binary
$DOCKER_CMD build \
    --platform "$PLATFORM" \
    --build-arg DEBUG_BUILD=$DEBUG_BUILD \
    --target builder \
    -f "$DOCKERFILE" \
    -t ginxsom-static-builder-stage:latest \
    . > /dev/null 2>&1

# Create a temporary container to copy the binary
CONTAINER_ID=$($DOCKER_CMD create ginxsom-static-builder-stage:latest)

# Copy binary from container
$DOCKER_CMD cp "$CONTAINER_ID:/build/ginxsom-fcgi_static" "$BUILD_DIR/$OUTPUT_NAME" || {
    echo "ERROR: Failed to extract binary from container"
    $DOCKER_CMD rm "$CONTAINER_ID" 2>/dev/null
    exit 1
}

# Clean up container
$DOCKER_CMD rm "$CONTAINER_ID" > /dev/null

echo "✓ Binary extracted to: $BUILD_DIR/$OUTPUT_NAME"
echo ""

# Make binary executable
chmod +x "$BUILD_DIR/$OUTPUT_NAME"

# Verify the binary
echo "=========================================="
echo "Step 3: Verifying static binary"
echo "=========================================="
echo ""

echo "Checking for dynamic dependencies:"
if LDD_OUTPUT=$(timeout 5 ldd "$BUILD_DIR/$OUTPUT_NAME" 2>&1); then
    if echo "$LDD_OUTPUT" | grep -q "not a dynamic executable"; then
        echo "✓ Binary is fully static (no dynamic dependencies)"
        TRULY_STATIC=true
    elif echo "$LDD_OUTPUT" | grep -q "statically linked"; then
        echo "✓ Binary is statically linked"
        TRULY_STATIC=true
    else
        echo "⚠ WARNING: Binary may have dynamic dependencies:"
        echo "$LDD_OUTPUT"
        TRULY_STATIC=false
    fi
else
    # ldd failed or timed out - check with file command instead
    if file "$BUILD_DIR/$OUTPUT_NAME" | grep -q "statically linked"; then
        echo "✓ Binary is statically linked (verified with file command)"
        TRULY_STATIC=true
    else
        echo "⚠ Could not verify static linking (ldd check failed)"
        TRULY_STATIC=false
    fi
fi
echo ""

echo "File size: $(ls -lh "$BUILD_DIR/$OUTPUT_NAME" | awk '{print $5}')"
echo ""

# Summary
echo "=========================================="
echo "Build Summary"
echo "=========================================="
echo "Binary: $BUILD_DIR/$OUTPUT_NAME"
echo "Size: $(du -h "$BUILD_DIR/$OUTPUT_NAME" | cut -f1)"
echo "Platform: $PLATFORM"
if [ "$DEBUG_BUILD" = true ]; then
    echo "Build Type: DEBUG (with symbols, no optimization)"
else
    echo "Build Type: PRODUCTION (optimized, stripped)"
fi
if [ "$TRULY_STATIC" = true ]; then
    echo "Linkage: Fully static binary (Alpine MUSL-based)"
    echo "Portability: Works on ANY Linux distribution"
else
    echo "Linkage: Static binary (may have minimal dependencies)"
fi
echo ""
echo "✓ Build complete!"
echo ""

# Clean up old dynamic build artifacts
echo "=========================================="
echo "Cleaning up old build artifacts"
echo "=========================================="
echo ""
if ls build/*.o 2>/dev/null | grep -q .; then
    echo "Removing old .o files from dynamic builds..."
    rm -f build/*.o
    echo "✓ Cleanup complete"
else
    echo "No .o files to clean"
fi

# Also remove old dynamic binary if it exists
if [ -f "build/ginxsom-fcgi" ]; then
    echo "Removing old dynamic binary..."
    rm -f build/ginxsom-fcgi
    echo "✓ Old binary removed"
fi

echo ""
echo "Deployment:"
echo "  scp $BUILD_DIR/$OUTPUT_NAME user@server:/path/to/ginxsom/"
echo ""
