# syntax=docker/dockerfile:1
#
# Salam compiler - multi-stage image (Alpine / musl, smallest practical base).
#

ARG ALPINE_VERSION=edge
ARG LLVM_VERSION=22

FROM alpine:${ALPINE_VERSION} AS toolchain
ARG LLVM_VERSION
SHELL ["/bin/ash", "-o", "pipefail", "-c"]

# trivy:ignore:AVD-DS-0025
RUN --mount=type=cache,target=/var/cache/apk,sharing=locked \
    for i in 1 2 3 4 5; do \
        apk add -U --cache-dir=/var/cache/apk \
            build-base \
            make \
            musl-dev \
            ccache \
            tcc \
            tcc-libs-static \
            clang${LLVM_VERSION} \
            llvm${LLVM_VERSION} \
            bash \
            git \
            sqlite-dev \
            sqlite-static \
            mariadb-connector-c-dev \
            hiredis-dev \
            openssl-dev \
            gtk+3.0-dev \
            webkit2gtk-4.1-dev \
            nodejs \
            npm \
            qemu-aarch64 \
            qemu-arm \
            qemu-i386 \
            wine \
        && break; \
        echo "apk add attempt $i failed; retrying in 5s..." >&2; sleep 5; \
        if [ "$i" = 5 ]; then \
            echo "apk add failed after 5 attempts; aborting build." >&2; \
            exit 1; \
        fi; \
    done

ENV WINEDEBUG=-all
ENV XDG_RUNTIME_DIR=/tmp/xdg-runtime

RUN mkdir -p "$XDG_RUNTIME_DIR" && chmod 0700 "$XDG_RUNTIME_DIR" \
    && timeout 60 wineboot --init >/tmp/wineboot-init.log 2>&1; \
    timeout 30 wineserver -w || wineserver -k || true; \
    if [ ! -f /root/.wine/system.reg ]; then \
        echo "wine prefix init failed:" >&2; cat /tmp/wineboot-init.log >&2; exit 1; \
    fi; \
    rm -f /tmp/wineboot-init.log

RUN node -v && npm -v

RUN set -eux; \
    LLVM_BIN="/usr/lib/llvm${LLVM_VERSION}/bin"; \
    for t in clang llc opt lli; do \
        if   [ -x "$LLVM_BIN/$t" ]; then src="$LLVM_BIN/$t"; \
        elif command -v "$t-${LLVM_VERSION}" >/dev/null 2>&1; then src="$(command -v "$t-${LLVM_VERSION}")"; \
        elif command -v "$t" >/dev/null 2>&1; then src="$(command -v "$t")"; \
        else echo "missing LLVM tool: $t" >&2; exit 1; fi; \
        ln -sf "$src" "/usr/local/bin/$t-${LLVM_VERSION}"; \
    done; \
    clang-${LLVM_VERSION} --version; \
    llc-${LLVM_VERSION} --version | head -1

ARG SALAM_UID=1000
ARG SALAM_GID=1000
RUN addgroup -g "${SALAM_GID}" salam \
    && adduser -D -u "${SALAM_UID}" -G salam salam

WORKDIR /app

FROM toolchain AS dev
# trivy:ignore:AVD-DS-0025
RUN --mount=type=cache,target=/var/cache/apk,sharing=locked \
    apk add -U --cache-dir=/var/cache/apk entr
RUN chown -R salam:salam /app \
    && mkdir -p /app/build \
    && chmod 1777 /app/build
ENV HOME=/tmp
USER salam
ENTRYPOINT ["sh", "tools/bash/docker-dev.sh"]

FROM toolchain AS builder
COPY c/ .
COPY std/ ./std
RUN make OUTDIR=. -j"$(nproc)" && make OUTDIR=. install PREFIX=/usr/local
RUN salam version

FROM toolchain AS prod
COPY --from=builder /usr/local/bin/salam /usr/local/bin/salam
COPY --from=builder /usr/local/share/salam /usr/local/share/salam

RUN mkdir -p /work && chown -R salam:salam /work
ENV HOME=/tmp
WORKDIR /work
USER salam

HEALTHCHECK --interval=5m --timeout=10s --start-period=5s --retries=3 \
    CMD salam version || exit 1

ENTRYPOINT ["salam"]
CMD ["help"]
