#!/usr/bin/env bash
# Markus Maiwald (Architect) | Voxis Forge (AI)


set -e

# Nexus Rumpk Build Script v0.4
# "Split Brain" Networking Edition

RUMPK_DIR=$(pwd)
BUILD_DIR="$RUMPK_DIR/build"
mkdir -p "$BUILD_DIR"

export ZIG_GLOBAL_CACHE_DIR="$BUILD_DIR/.zig-cache"
export ZIG_LOCAL_CACHE_DIR="$BUILD_DIR/.zig-cache-local"

ARCH=${1:-riscv64}

case $ARCH in
    riscv64)
        ZIG_TARGET="riscv64-freestanding-none"
        ZIG_OBJ_FLAGS="-mcpu=sifive_u54 -mcmodel=medany"
        ARCH_FLAGS="-mcpu=sifive_u54 -mabi=lp64d -mcmodel=medany -ffunction-sections -fdata-sections"
        NIM_CPU="riscv64"
        NIM_DEFINE="riscv64"
        ENTRY_FILE="riscv"
        ;;
    x86_64)
        ZIG_TARGET="x86_64-freestanding-none"
        ARCH_FLAGS="-mno-red-zone"
        NIM_CPU="amd64"
        NIM_DEFINE="x86_64"
        ENTRY_FILE="x86_64"
        ;;
    aarch64)
        ZIG_TARGET="aarch64-freestanding-none"
        ARCH_FLAGS=""
        NIM_CPU="arm64"
        NIM_DEFINE="aarch64"
        ENTRY_FILE="aarch64"
        ;;
    *)
        echo "Unsupported architecture: $ARCH"
        exit 1
        ;;
esac

echo "╔═══════════════════════════════════════╗"
echo "║    RUMPK MULTI-ARCH BUILD v0.4        ║"
echo "║    Architecture: $ARCH                 "
echo "╚═══════════════════════════════════════╝"

# =========================================================
# Step 1: Compile Zig L0 (HAL + libc stubs)
# =========================================================
echo "[1/8] Compiling Zig L0 (HAL + libc stubs)..."
zig build-obj \
    -target $ZIG_TARGET \
    $ZIG_OBJ_FLAGS \
    -O ReleaseFast \
    "$RUMPK_DIR/hal/entry_$ENTRY_FILE.zig" \
    --name hal

mv hal.o "$BUILD_DIR/hal.o"
echo "      → $BUILD_DIR/hal.o"

zig build-obj \
    -target $ZIG_TARGET \
    $ZIG_OBJ_FLAGS \
    -O ReleaseFast \
    "$RUMPK_DIR/hal/stubs.zig" \
    --name stubs

mv stubs.o "$BUILD_DIR/stubs.o"
echo "      → $BUILD_DIR/stubs.o"

zig build-obj \
    -target $ZIG_TARGET \
    $ZIG_OBJ_FLAGS \
    -O ReleaseFast \
    "$RUMPK_DIR/hal/channel.zig" \
    --name channel

mv channel.o "$BUILD_DIR/channel.o"
echo "      → $BUILD_DIR/channel.o"

# Compile NexShell NPL (Immune System Voice)
echo "[1.1/8] Compiling NexShell NPL..."
zig build-obj \
    -target $ZIG_TARGET \
    $ZIG_OBJ_FLAGS \
    -O ReleaseFast \
    "$RUMPK_DIR/src/npl/system/nexshell.zig" \
    --name nexshell

mv nexshell.o "$BUILD_DIR/nexshell.o"
echo "      → $BUILD_DIR/nexshell.o"

# Compile UI (Zicroui)
echo "[1.2/8] Compiling UI (Zicroui)..."
zig build-obj \
    -target $ZIG_TARGET \
    $ZIG_OBJ_FLAGS \
    -O ReleaseFast \
    -I"$RUMPK_DIR/libs/microui" \
    "$RUMPK_DIR/hal/ui.zig" \
    --name ui

mv ui.o "$BUILD_DIR/ui.o"
echo "      → $BUILD_DIR/ui.o"

# Compile GPU Driver (Retina)
echo "[1.3/8] Compiling GPU Driver (VirtIO-GPU)..."
zig build-obj \
    -target $ZIG_TARGET \
    $ZIG_OBJ_FLAGS \
    -O ReleaseFast \
    "$RUMPK_DIR/hal/gpu.zig" \
    --name gpu

mv gpu.o "$BUILD_DIR/gpu.o"
echo "      → $BUILD_DIR/gpu.o"

# Compile Matrix Protocol (Rainmaker)
echo "[1.4/8] Compiling Matrix Protocol..."
zig build-obj \
    -target $ZIG_TARGET \
    $ZIG_OBJ_FLAGS \
    -O ReleaseFast \
    "$RUMPK_DIR/hal/matrix.zig" \
    --name matrix

mv matrix.o "$BUILD_DIR/matrix.o"
echo "      → $BUILD_DIR/matrix.o"

# =========================================================
# Step 2: Compile context switch assembly
# =========================================================
echo "[2/8] Compiling context switch ($ARCH)..."
zig cc \
    -target $ZIG_TARGET \
    $ARCH_FLAGS \
    -ffreestanding \
    -c "$RUMPK_DIR/hal/arch/$ARCH/switch.S" \
    -o "$BUILD_DIR/switch.o"
echo "      → $BUILD_DIR/switch.o"

# =========================================================
# Step 2.1: Compile Monocypher
# =========================================================
echo "[2.1/8] Compiling Monocypher..."
zig cc \
    -target $ZIG_TARGET \
    -ffreestanding \
    -fno-stack-protector \
    -fno-builtin \
    -O3 \
    -c "$RUMPK_DIR/hal/crypto/monocypher.c" \
    -o "$BUILD_DIR/monocypher.o"
echo "      → $BUILD_DIR/monocypher.o"

# =========================================================
# Step 2.1b: Compile Microui
# =========================================================
echo "[2.1b/8] Compiling Microui..."
zig cc \
    -target $ZIG_TARGET \
    $ARCH_FLAGS \
    -ffreestanding \
    -fno-stack-protector \
    -fno-builtin \
    -O3 \
    -I"$RUMPK_DIR/libs/microui/include" \
    -c "$RUMPK_DIR/libs/microui/microui.c" \
    -o "$BUILD_DIR/microui.o"
echo "      → $BUILD_DIR/microui.o"

# =========================================================
# Step 2.2: Compile LwIP (Kernel Stack)
# =========================================================
# echo "[2.2/8] Compiling LwIP (Kernel)..."
# LWIP_CORE_FILES=(
#     "src/core/init.c"
#     "src/core/def.c"
#     "src/core/dns.c"
#     "src/core/inet_chksum.c"
#     "src/core/ip.c"
#     "src/core/mem.c"
#     "src/core/memp.c"
#     "src/core/netif.c"
#     "src/core/pbuf.c"
#     "src/core/raw.c"
#     "src/core/stats.c"
#     "src/core/sys.c"
#     "src/core/tcp.c"
#     "src/core/tcp_in.c"
#     "src/core/tcp_out.c"
#     "src/core/timeouts.c"
#     "src/core/udp.c"
#     "src/core/ipv4/autoip.c"
#     "src/core/ipv4/dhcp.c"
#     "src/core/ipv4/etharp.c"
#     "src/core/ipv4/icmp.c"
#     "src/core/ipv4/igmp.c"
#     "src/core/ipv4/ip4.c"
#     "src/core/ipv4/ip4_addr.c"
#     "src/core/ipv4/ip4_frag.c"
#     "src/netif/ethernet.c"
# )
# 
# for cfile in "${LWIP_CORE_FILES[@]}"; do
#     cfile_path="$RUMPK_DIR/vendor/lwip/$cfile"
#     objname=$(basename "$cfile" .c)
#     zig cc \
#         -target $ZIG_TARGET \
#         $ARCH_FLAGS \
#         -ffreestanding \
#         -fno-stack-protector \
#         -fno-builtin \
#         -O2 \
#         -I"$RUMPK_DIR/core/include" \
#         -I"$RUMPK_DIR/core/net" \
#         -I"$RUMPK_DIR/vendor/lwip/src/include" \
#         -c "$cfile_path" \
#         -o "$BUILD_DIR/lwip_kernel_$objname.o"
# done

# =========================================================
# Step 2.3: Compile LwIP (Membrane Stack)
# =========================================================
echo "[2.3/8] Skipping LwIP (Removed)..."
# LwIP was removed from the build
LWIP_MEMBRANE_OBJS=""

# Compile sys_arch.c (LwIP Platform Abstraction)
echo "[2.4/8] Compiling LwIP Platform Layer (sys_arch.c)..."
# zig cc \
#     -target $ZIG_TARGET \
#     $ARCH_FLAGS \
#     -ffreestanding \
#     -fno-stack-protector \
#     -fno-builtin \
#     -O2 \
#     -I"$RUMPK_DIR/core/include" \
#     -I"$RUMPK_DIR/core/net" \
#     -I"$RUMPK_DIR/vendor/lwip/src/include" \
#     -c "$RUMPK_DIR/core/net/sys_arch.c" \
#     -o "$BUILD_DIR/sys_arch.o"
# 
# echo "      → LwIP objects compiled."

# =========================================================
# Step 3: Compile Nim L1 (Kernel + Fibers)
# =========================================================
echo "[3/8] Compiling Nim L1 (Kernel + Fibers)..."
mkdir -p "$BUILD_DIR/nimcache"
nim c \
    --cpu:$NIM_CPU \
    --os:any \
    --mm:arc \
    --noMain:on \
    --cc:clang \
    --passC:"-target ${ZIG_TARGET/-freestanding-none/-unknown-none} -ffreestanding -fno-stack-protector -fno-builtin $ARCH_FLAGS -I$RUMPK_DIR/core/include -O3 -flto" \
    --define:useMalloc \
    --define:nimNoLibc \
    --define:noSignalHandler \
    --define:$NIM_DEFINE \
    -d:danger \
    --opt:speed \
    --nimcache:"$BUILD_DIR/nimcache" \
    --path:"$RUMPK_DIR/core" \
    -c \
    "$RUMPK_DIR/core/kernel.nim"

# =========================================================
# Step 4: Compile Nim C files
# =========================================================
echo "[4/8] Compiling Nim C files..."
zig cc \
    -target $ZIG_TARGET \
    $ARCH_FLAGS \
    -ffreestanding \
    -fno-stack-protector \
    -fno-builtin \
    -O2 \
    -I"$RUMPK_DIR/core/include" \
    -c "$RUMPK_DIR/core/cstubs.c" \
    -o "$BUILD_DIR/cstubs.o"
echo "      → $BUILD_DIR/cstubs.o"

NIM_OBJS=""
for cfile in "$BUILD_DIR/nimcache"/*.c; do
    ofile="${cfile%.c}.o"
    zig cc \
        -target $ZIG_TARGET \
        -ffreestanding \
        -fno-stack-protector \
        -fno-builtin \
        -fno-sanitize=all \
        $ARCH_FLAGS \
        -I"$RUMPK_DIR/core/include" \
        -I/usr/lib/nim \
        -I"$RUMPK_DIR/core" \
        -O3 -flto \
        -c "$cfile" \
        -o "$ofile"
    NIM_OBJS="$NIM_OBJS $ofile"
done
echo "      → $BUILD_DIR/nimcache/*.o"

# =========================================================
# Step 4.1: Compile Overrides (Math/Atomics Stubs)
# =========================================================
echo "[4.1/8] Compiling Sovereign Overrides..."
zig cc \
    -target $ZIG_TARGET \
    $ARCH_FLAGS \
    -ffreestanding \
    -fno-stack-protector \
    -fno-builtin \
    -O2 \
    -I"$RUMPK_DIR/core/include" \
    -c "$RUMPK_DIR/core/overrides.c" \
    -o "$BUILD_DIR/overrides.o"
echo "      → $BUILD_DIR/overrides.o"

# =========================================================
# Step 5: Compile Membrane Library (libnexus.a)
# =========================================================
echo "[5/8] Compiling Membrane Library (libnexus.a)..."
mkdir -p "$BUILD_DIR/membrane_nimcache"

# Compile clib.c (The Mini-Libc)
zig cc \
    -target $ZIG_TARGET \
    $ARCH_FLAGS \
    -ffreestanding \
    -fno-stack-protector \
    -fno-builtin \
    -O2 \
    -I"$RUMPK_DIR/core/include" \
    -c "$RUMPK_DIR/libs/membrane/clib.c" \
    -o "$BUILD_DIR/clib.o"

# Compile sys_arch.c (Membrane LwIP Platform Layer)
zig cc \
    -target $ZIG_TARGET \
    $ARCH_FLAGS \
    -ffreestanding \
    -fno-stack-protector \
    -fno-builtin \
    -O2 \
    -I"$RUMPK_DIR/core/include" \
    -I"$RUMPK_DIR/libs/membrane/include" \
    -I"$RUMPK_DIR/vendor/lwip/src/include" \
    -c "$RUMPK_DIR/libs/membrane/sys_arch.c" \
    -o "$BUILD_DIR/membrane_sys_arch.o"

nim c \
    --cpu:$NIM_CPU \
    --os:any \
    -d:is_membrane \
    -d:danger \
    --opt:speed \
    -d:useMalloc \
    -d:nimNoLibc \
    -d:noSignalHandler \
    --gc:arc \
    --panics:on \
    --app:staticlib \
    --nimMainPrefix:Membrane \
    --hint:Conf:off \
    --hint:OSLib:off \
    --nimcache:"$BUILD_DIR/membrane_nimcache" \
    --path:"$RUMPK_DIR/libs/membrane" \
    --path:"$RUMPK_DIR/core" \
    -c \
    "$RUMPK_DIR/libs/membrane/libc.nim"

MEMBRANE_NIM_OBJS=""
for cfile in "$BUILD_DIR/membrane_nimcache"/*.c; do
    ofile="${cfile%.c}.o"
    zig cc \
        -target $ZIG_TARGET \
        -ffreestanding \
        -fno-stack-protector \
        -fno-builtin \
        -fno-sanitize=all \
        $ARCH_FLAGS \
        -I"$RUMPK_DIR/core/include" \
        -I/usr/lib/nim \
        -I"$RUMPK_DIR/core" \
        -I"$RUMPK_DIR/libs/membrane" \
        -I"$RUMPK_DIR/libs/membrane/include" \
        -I"$RUMPK_DIR/vendor/lwip/src/include" \
        -O3 -flto \
        -c "$cfile" \
        -o "$ofile"
    MEMBRANE_NIM_OBJS="$MEMBRANE_NIM_OBJS $ofile"
done

# =========================================================
# Step 5.1: [MOVED] NipBox compilation happens AFTER libnexus.a
# =========================================================
# NipBox requires libnexus.a to link, so it's compiled at Step 5.6
echo "[5.1/8] Skipping Subject (NipBox will be compiled after Membrane)..."

# =========================================================
# Step 5.5: Patch Atomic References & Nuke Cache (GLOBAL)
# =========================================================
# We must do this BEFORE creating archives or linking anything.
# This ensures broken libcompiler_rt refs are removed from ALL objects.

echo "[5.5/8] Patching Atomic References & Nuking Cache..."

find "$BUILD_DIR" -name "*.o" | while read obj; do
    zig objcopy --redefine-syms="$RUMPK_DIR/core/re-symbol.txt" "$obj" "$obj" 2>/dev/null || true
    # Remove auto-linking sections
    zig objcopy \
        --remove-section .linker-options \
        --remove-section .comment \
        --remove-section .deplibs \
        --remove-section .llvm_addrsig \
        --remove-section .dependent-lib \
        "$obj" "$obj" 2>/dev/null || true
done

echo "      → SWAPPING libcompiler_rt.a with dummy archive (GLOB)..."
echo "" > "$BUILD_DIR/dummy.c"
zig cc -target $ZIG_TARGET -c "$BUILD_DIR/dummy.c" -o "$BUILD_DIR/dummy.o" $ARCH_FLAGS

for lib in "$BUILD_DIR"/.zig-cache/o/*/libcompiler_rt.a; do
    if [ -f "$lib" ]; then
        echo "        Replacing $lib"
        rm -f "$lib"
        zig ar rc "$lib" "$BUILD_DIR/dummy.o"
    fi
done

# =========================================================
# Step 5b: Create Membrane Archive
# =========================================================

# Note: We manually include ion_switch.o from the KERNEL nimcache if needed,
# but it should be in membrane_nimcache too because libc.nim imports it.
# Let's verify if ion_switch.o exists in membrane_nimcache.
ION_SWITCH_OBJ=$(ls "$BUILD_DIR/membrane_nimcache"/*ion_switch*o 2>/dev/null || echo "")

zig ar rc "$BUILD_DIR/libnexus.a" \
    $MEMBRANE_NIM_OBJS \
    $LWIP_MEMBRANE_OBJS \
    "$BUILD_DIR/clib.o" \
    "$BUILD_DIR/membrane_sys_arch.o" \
    "$BUILD_DIR/switch.o"

echo "      → $BUILD_DIR/libnexus.a"

# =========================================================
# Step 5.6: Compile NipBox (The Sovereign Userland)
# =========================================================
echo "[5.6/8] Compiling NipBox (Sovereign Userland)..."

# Stage 1: Let Nim generate C code only (no linking)
nim c \
    --cpu:$NIM_CPU \
    --os:any \
    -d:danger \
    --opt:size \
    -d:useMalloc \
    -d:nimNoLibc \
    -d:noSignalHandler \
    --mm:arc \
    --checks:off \
    --panics:on \
    --noMain:off \
    --hint:Conf:off \
    --hint:OSLib:off \
    --nimcache:"$BUILD_DIR/nipbox_nimcache" \
    --path:"$RUMPK_DIR/libs/membrane" \
    --path:"$RUMPK_DIR/core" \
    --compileOnly \
    "$RUMPK_DIR/npl/nipbox/nipbox.nim"

# Stage 2: Compile all C files with zig cc
echo "[5.6.1/8] Compiling NipBox C files with zig cc..."
NIPBOX_OBJS=""
find "$BUILD_DIR/nipbox_nimcache" -name "*.c" | while read cfile; do
    ofile="${cfile%.c}.o"
    zig cc \
        -target $ZIG_TARGET \
        $ARCH_FLAGS \
        -ffreestanding \
        -fno-stack-protector \
        -fno-builtin \
        -Os \
        -ffunction-sections \
        -fdata-sections \
        -I/usr/lib/nim \
        -I"$RUMPK_DIR/core/include" \
        -c "$cfile" \
        -o "$ofile"
done

# Collect all object files
NIPBOX_OBJS=$(find "$BUILD_DIR/nipbox_nimcache" -name "*.o" | tr '\n' ' ')

# Stage 2.5: Compile libc_shim.zig (Universal Adapter)
echo "[5.6.1b/8] Compiling libc_shim.zig..."
zig build-obj \
    -target $ZIG_TARGET \
    $ZIG_OBJ_FLAGS \
    -O ReleaseSmall \
    "$RUMPK_DIR/libs/membrane/libc_shim.zig" \
    --name libc_shim

mv libc_shim.o "$BUILD_DIR/libc_shim.o"

# Stage 2.6: Compile subject_entry.S
echo "[5.6.1c/8] Compiling subject_entry.S..."
zig cc -target $ZIG_TARGET -ffreestanding -c "$RUMPK_DIR/apps/subject_entry.S" -o "$BUILD_DIR/subject_entry.o"

# Stage 3: Link with zig cc
echo "[5.6.2/8] Linking NipBox binary..."
zig cc \
    -target $ZIG_TARGET \
    $ARCH_FLAGS \
    -ffreestanding \
    -fno-stack-protector \
    -nostdlib \
    -static \
    -Wl,--gc-sections \
    -T "$RUMPK_DIR/apps/linker_user.ld" \
    "$BUILD_DIR/subject_entry.o" \
    "$BUILD_DIR/stubs.o" \
    $NIPBOX_OBJS \
    "$BUILD_DIR/libc_shim.o" \
    -L"$BUILD_DIR" \
    -lnexus \
    -o "$BUILD_DIR/nipbox"

mkdir -p "$RUMPK_DIR/rootfs/bin"
cp "$BUILD_DIR/nipbox" "$RUMPK_DIR/rootfs/bin/nipbox"
echo "      → rootfs/bin/nipbox"

# Convert NipBox binary to object file for embedding
echo "[5.6.3/8] Embedding NipBox as Subject..."
llvm-objcopy -O binary "$BUILD_DIR/nipbox" "$BUILD_DIR/nipbox.bin"

# Generate assembly wrapper for safe embedding
cat <<EOF > "$BUILD_DIR/subject_wrapper.S"
.section .rodata
.global _subject_start
.global _subject_end
_subject_start:
    .incbin "$BUILD_DIR/nipbox.bin"
_subject_end:
EOF

# Compile wrapper to object file
zig cc \
    -target $ZIG_TARGET \
    -c "$BUILD_DIR/subject_wrapper.S" \
    -o "$BUILD_DIR/subject_zig.o"

echo "      → $BUILD_DIR/nipbox ($(stat -c%s "$BUILD_DIR/nipbox" 2>/dev/null || echo "unknown") bytes)"
echo "      → $BUILD_DIR/subject_zig.o (embedded)"

# =========================================================
# Step 5.7: Compile Hello Alien (Test Binary)
# =========================================================
echo "[5.7/8] Compiling Hello Alien..."
zig cc \
    -target $ZIG_TARGET \
    $ARCH_FLAGS \
    -ffreestanding \
    -fno-stack-protector \
    -fno-builtin \
    -Os \
    -I"$RUMPK_DIR/rootfs/src" \
    -I"$RUMPK_DIR/core/include" \
    -c "$RUMPK_DIR/rootfs/src/hello.c" \
    -o "$BUILD_DIR/hello.o"

zig cc \
    -target $ZIG_TARGET \
    $ARCH_FLAGS \
    -ffreestanding \
    -fno-stack-protector \
    -nostdlib \
    -static \
    -Wl,--gc-sections \
    -T "$RUMPK_DIR/apps/linker_user.ld" \
    "$BUILD_DIR/subject_entry.o" \
    "$BUILD_DIR/hello.o" \
    "$BUILD_DIR/libc_shim.o" \
    -L"$BUILD_DIR" \
    -lnexus \
    -o "$RUMPK_DIR/rootfs/bin/hello"

echo "      → rootfs/bin/hello"

# Copy nipbox to rootfs/bin for TarFS loading
mkdir -p "$RUMPK_DIR/rootfs/bin"
cp "$BUILD_DIR/nipbox" "$RUMPK_DIR/rootfs/bin/nipbox"

# =========================================================
# Step 6: Final Kernel Assembly
# =========================================================
echo "[6/8] Linking Subject Zero (Canary)..."

# Note: subject_zero.o and libnexus.a are already compiled and patched.

# =========================================================
# Step 6: Link Subject Zig
# =========================================================
echo "[6/8] Linking Subject Zig..."

zig cc \
    -target $ZIG_TARGET \
    -nostdlib \
    -T "$RUMPK_DIR/apps/linker_user.ld" \
    "$BUILD_DIR/subject_zig.o" \
    "$BUILD_DIR/libnexus.a" \
    -o "$BUILD_DIR/subject.elf" \
    -lgcc

echo "      → $BUILD_DIR/subject.elf"
zig objcopy -O binary "$BUILD_DIR/subject.elf" "$BUILD_DIR/subject.bin"
echo "      → $BUILD_DIR/subject.bin"

# =========================================================
# Step 7: Compile Loader (After Subject)
# =========================================================
echo "[7/8] Compiling Loader (with Embedded Subject)..."

# Copy nipbox.bin to core/ so loader.zig can embed it (replacing stale subject.bin)
cp "$BUILD_DIR/nipbox.bin" "$RUMPK_DIR/core/subject.bin"

zig build-obj \
    -target $ZIG_TARGET \
    $ZIG_OBJ_FLAGS \
    -O ReleaseFast \
    "$RUMPK_DIR/core/loader.zig" \
    --name loader
mv loader.o "$BUILD_DIR/loader.o"
echo "      → $BUILD_DIR/loader.o"

# Clean up temp file
rm "$RUMPK_DIR/core/subject.bin"

# Patch Loader Object specifically
echo "      → Patching Loader Object..."
obj="$BUILD_DIR/loader.o"
zig objcopy --redefine-syms="$RUMPK_DIR/core/re-symbol.txt" "$obj" "$obj" 2>/dev/null || true
zig objcopy \
    --remove-section .linker-options \
    --remove-section .comment \
    --remove-section .deplibs \
    --remove-section .llvm_addrsig \
    --remove-section .dependent-lib \
    "$obj" "$obj" 2>/dev/null || true

# =========================================================
# Step 7.5: Package RootFS (Sovereign VFS)
# =========================================================
echo "[7.5/8] Packaging RootFS (InitRD)..."
# tar --format=ustar -cf "$BUILD_DIR/initrd.tar" -C "$RUMPK_DIR/rootfs" . 2>/dev/null || touch "$BUILD_DIR/initrd.tar"
echo "      → Invoking Nexus Forge..."
pushd ../.. > /dev/null
./nexus build
popd > /dev/null

# Generate assembly wrapper for safe embedding
cat <<EOF > "$BUILD_DIR/initrd_wrapper.S"
.section .rodata
.balign 512
.global _initrd_start
.global _initrd_end
_initrd_start:
    .incbin "$BUILD_DIR/initrd.tar"
_initrd_end:
EOF

zig cc \
    -target $ZIG_TARGET \
    $ARCH_FLAGS \
    -ffreestanding \
    -c "$BUILD_DIR/initrd_wrapper.S" \
    -o "$BUILD_DIR/initrd.o"

echo "      → $BUILD_DIR/initrd.o ($(stat -c%s "$BUILD_DIR/initrd.o" 2>/dev/null || echo "unknown") bytes)"

# =========================================================
# Step 8: Link Kernel (Direct LLD Bypass)
# =========================================================
echo "[8/8] Linking Kernel ($ARCH) using LLD..."

# Check if ld.lld is available, otherwise assume zig cc wrapper but we try direct first
LINKER="ld.lld"
EMULATION=""

if [ "$ARCH" = "riscv64" ]; then
    EMULATION="-m elf64lriscv"
elif [ "$ARCH" = "x86_64" ]; then
    EMULATION="-m elf_x86_64"
elif [ "$ARCH" = "aarch64" ]; then
    EMULATION="-m aarch64elf"
fi

$LINKER \
    -t \
    $EMULATION \
    --gc-sections \
    -T "$RUMPK_DIR/hal/arch/$ARCH/linker.ld" \
    "$BUILD_DIR/hal.o" \
    "$BUILD_DIR/stubs.o" \
    "$BUILD_DIR/channel.o" \
    "$BUILD_DIR/switch.o" \
    "$BUILD_DIR/monocypher.o" \
    "$BUILD_DIR/cstubs.o" \
    "$BUILD_DIR/overrides.o" \
    "$BUILD_DIR/loader.o" \
    "$BUILD_DIR/nexshell.o" \
    "$BUILD_DIR/ui.o" \
    "$BUILD_DIR/gpu.o" \
    "$BUILD_DIR/matrix.o" \
    "$BUILD_DIR/initrd.o" \
    "$BUILD_DIR/microui.o" \
    $NIM_OBJS \
    -o "$BUILD_DIR/rumpk-$ARCH.elf"

echo "      → $BUILD_DIR/rumpk-$ARCH.elf"

echo ""
echo "✅ Build complete for $ARCH!"
echo "Run with:"
echo "  qemu-system-riscv64 -M virt -nographic -kernel $BUILD_DIR/rumpk-riscv64.elf -netdev user,id=n0 -device virtio-net-pci,netdev=n0,disable-modern=on"
echo ""
