# Alpine-based MUSL static binary builder for C-Relay
# Produces truly portable binaries with zero runtime dependencies

ARG DEBUG_BUILD=false

FROM alpine:3.19 AS builder

# Install build dependencies
RUN apk add --no-cache \
    build-base \
    musl-dev \
    git \
    cmake \
    pkgconfig \
    autoconf \
    automake \
    libtool \
    openssl-dev \
    openssl-libs-static \
    zlib-dev \
    zlib-static \
    curl-dev \
    curl-static \
    sqlite-dev \
    sqlite-static \
    linux-headers \
    wget \
    bash

# Set working directory
WORKDIR /build

# Build libsecp256k1 static (cached layer - only rebuilds if Alpine version changes)
RUN cd /tmp && \
    git clone https://github.com/bitcoin-core/secp256k1.git && \
    cd secp256k1 && \
    ./autogen.sh && \
    ./configure --enable-static --disable-shared --prefix=/usr \
        CFLAGS="-fPIC" && \
    make -j$(nproc) && \
    make install && \
    rm -rf /tmp/secp256k1

# Build libwebsockets static with minimal features (cached layer)
RUN cd /tmp && \
    git clone --depth 1 --branch v4.3.3 https://github.com/warmcat/libwebsockets.git && \
    cd libwebsockets && \
    mkdir build && cd build && \
    cmake .. \
        -DLWS_WITH_STATIC=ON \
        -DLWS_WITH_SHARED=OFF \
        -DLWS_WITH_SSL=ON \
        -DLWS_WITHOUT_TESTAPPS=ON \
        -DLWS_WITHOUT_TEST_SERVER=ON \
        -DLWS_WITHOUT_TEST_CLIENT=ON \
        -DLWS_WITHOUT_TEST_PING=ON \
        -DLWS_WITH_HTTP2=OFF \
        -DLWS_WITH_LIBUV=OFF \
        -DLWS_WITH_LIBEVENT=OFF \
        -DLWS_IPV6=ON \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_INSTALL_PREFIX=/usr \
        -DCMAKE_C_FLAGS="-fPIC" && \
    make -j$(nproc) && \
    make install && \
    rm -rf /tmp/libwebsockets

# Copy only submodule configuration and git directory
COPY .gitmodules /build/.gitmodules
COPY .git /build/.git

# Clean up any stale submodule references (nips directory is not a submodule)
RUN git rm --cached nips 2>/dev/null || true

# Initialize submodules (cached unless .gitmodules changes)
RUN git submodule update --init --recursive

# Copy nostr_core_lib source files (cached unless nostr_core_lib changes)
COPY nostr_core_lib /build/nostr_core_lib/

# Copy c_utils_lib source files (cached unless c_utils_lib changes)
COPY c_utils_lib /build/c_utils_lib/

# Build c_utils_lib with MUSL-compatible flags (cached unless c_utils_lib changes)
RUN cd c_utils_lib && \
    sed -i 's/CFLAGS = -Wall -Wextra -std=c99 -O2 -g/CFLAGS = -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -Wall -Wextra -std=c99 -O2 -g/' Makefile && \
    make clean && \
    make

# Build nostr_core_lib with required NIPs (cached unless nostr_core_lib changes)
# Disable fortification in build.sh to prevent __*_chk symbol issues
# NIPs: 001(Basic), 006(Keys), 013(PoW), 017(DMs), 019(Bech32), 044(Encryption), 059(Gift Wrap - required by NIP-17)
RUN cd nostr_core_lib && \
    chmod +x build.sh && \
    sed -i 's/CFLAGS="-Wall -Wextra -std=c99 -fPIC -O2"/CFLAGS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 -Wall -Wextra -std=c99 -fPIC -O2"/' build.sh && \
    rm -f *.o *.a 2>/dev/null || true && \
    ./build.sh --nips=1,6,13,17,19,44,59

# Copy c-relay source files LAST (only this layer rebuilds on source changes)
COPY src/ /build/src/
COPY Makefile /build/Makefile

# Build c-relay with full static linking (only rebuilds when src/ changes)
# Disable fortification to avoid __*_chk symbols that don't exist in MUSL
# Use conditional compilation flags based on DEBUG_BUILD argument
RUN if [ "$DEBUG_BUILD" = "true" ]; then \
        CFLAGS="-g -O0 -DDEBUG"; \
        STRIP_CMD=""; \
        echo "Building with DEBUG symbols enabled"; \
    else \
        CFLAGS="-O2"; \
        STRIP_CMD="strip /build/c_relay_static"; \
        echo "Building optimized production binary"; \
    fi && \
    gcc -static $CFLAGS -Wall -Wextra -std=c99 \
    -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 \
    -I. -Ic_utils_lib/src -Inostr_core_lib -Inostr_core_lib/nostr_core \
    -Inostr_core_lib/cjson -Inostr_core_lib/nostr_websocket \
    src/main.c src/config.c src/dm_admin.c src/request_validator.c \
    src/nip009.c src/nip011.c src/nip013.c src/nip040.c src/nip042.c \
    src/websockets.c src/subscriptions.c src/api.c src/embedded_web_content.c \
    -o /build/c_relay_static \
    c_utils_lib/libc_utils.a \
    nostr_core_lib/libnostr_core_x64.a \
    -lwebsockets -lssl -lcrypto -lsqlite3 -lsecp256k1 \
    -lcurl -lz -lpthread -lm -ldl && \
    eval "$STRIP_CMD"

# Verify it's truly static
RUN echo "=== Binary Information ===" && \
    file /build/c_relay_static && \
    ls -lh /build/c_relay_static && \
    echo "=== Checking for dynamic dependencies ===" && \
    (ldd /build/c_relay_static 2>&1 || echo "Binary is static") && \
    echo "=== Build complete ==="

# Output stage - just the binary
FROM scratch AS output
COPY --from=builder /build/c_relay_static /c_relay_static