# Explore container for flaredown — rubyforgood chronic-illness symptom tracker.
# github.com/rubyforgood/Flaredown (GPL-3), pinned upstream at 5f859e8d. Polyglot, multi-service:
#   - backend/  Rails 7.1 API, Ruby 3.2.3. Mongoid 8.1 on MongoDB (primary store) + Postgres
#     (small relational slice) + Redis + Sidekiq.
#   - frontend/ Ember.js client, Node 14.21.3 (npm 7).
# Adapted for live-mount: the source repo is bind-mounted at /workspace/repo; deps + DB set up
# by post-create.sh, and the three datastores are started by post-start.sh.
#
# Deliberate version choice: docker-compose pins MongoDB 4.4.9, which is EOL and ships no
# arm64 / Debian-bookworm packages. Mongoid 8.1.3 + the mongo ruby driver 2.20.1 support
# servers up to 7.0, so we run MongoDB 7.0 (native amd64 + aarch64, no emulation) instead of
# fighting a dead 4.4 build. Same wire protocol; the app is version-agnostic here.
FROM ruby:3.2.3

# System deps: Postgres + libpq (the pg gem), Redis (Sidekiq), plus build tooling. python3
# (bookworm ships 3.11 ≥ 3.10, which the reduced-toolset str_replace_editor needs). xz/curl/
# gnupg for the Node + Mongo downloads. libyaml for psych.
RUN apt-get update && apt-get install -y --no-install-recommends \
      postgresql postgresql-client libpq-dev \
      redis-server \
      build-essential pkg-config libyaml-dev \
      python3 \
      git sudo curl ca-certificates gnupg xz-utils procps \
 && rm -rf /var/lib/apt/lists/*

# MongoDB 7.0 server binary (mongod) from the official tarball, arch-aware. The ubuntu2204
# build (glibc 2.35) runs fine on bookworm (glibc 2.36). Only mongod is needed — Mongoid
# connects over the wire; no mongosh required (post-start probes the port directly).
RUN set -eux; \
    arch="$(dpkg --print-architecture)"; \
    case "$arch" in \
      amd64) marm=x86_64;; \
      arm64) marm=aarch64;; \
      *) echo "unsupported arch: $arch" >&2; exit 1;; \
    esac; \
    ver=7.0.14; \
    curl -fsSL "https://fastdl.mongodb.org/linux/mongodb-linux-${marm}-ubuntu2204-${ver}.tgz" -o /tmp/mongo.tgz; \
    tar -xzf /tmp/mongo.tgz -C /tmp; \
    cp /tmp/mongodb-linux-${marm}-ubuntu2204-${ver}/bin/mongod /usr/local/bin/; \
    rm -rf /tmp/mongo.tgz /tmp/mongodb-linux-*; \
    mongod --version | head -1

# Node via nvm: 18 (default — toolkit tooling: create-snapshot hooks, `node -e` reads of
# toolkit.json) + 14 (the Ember app; frontend/.nvmrc = v14.21.3). Symlink v18 to /usr/local/bin
# so the toolkit's own node always resolves; run-app switches PATH to v14 for the client.
# The frontend's .npmrc sets engine-strict=true and its package.json requires npm 6.x, so pin
# npm 6 in the v14 line (nvm's 14.21.3 otherwise bundles npm 7, which fails engine-strict). The
# v18.* glob (not `nvm version`) avoids sourcing nvm.sh under Docker's /bin/sh (dash), bash-only.
ENV NVM_DIR=/usr/local/nvm
RUN mkdir -p "$NVM_DIR" \
 && curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash \
 && bash -c '. "$NVM_DIR/nvm.sh" \
      && nvm install 18 \
      && nvm install 14.21.3 && nvm use 14.21.3 && npm install -g npm@6.14.18 \
      && nvm alias default 18' \
 && for b in node npm npx; do ln -sf "$NVM_DIR"/versions/node/v18.*/bin/"$b" /usr/local/bin/"$b"; done \
 && node --version

# phantomjs stub. The Ember client depends on phantomjs-prebuilt@2.1.16, which has NO arm64
# binary and is EOL everywhere — its install script aborts `npm install` on Apple-Silicon
# hosts. A stub on PATH that reports the expected version makes the install script treat
# PhantomJS as "already installed" and skip the (impossible) download, so `npm install`
# completes and `ember build`/`ember serve` (what run-app uses) work. `ember test` runs on
# headless Chrome at this pin, wired up after the Playwright block below.
RUN printf '#!/bin/bash\n[ "$1" = "--version" ] && { echo "2.1.1"; exit 0; }\nexit 0\n' > /usr/local/bin/phantomjs \
 && chmod +x /usr/local/bin/phantomjs

# Match backend/Gemfile.lock "BUNDLED WITH 2.5.6".
RUN gem install bundler -v 2.5.6

# Postgres trust auth: backend/config/database.yml connects as PG_DATABASE_USERNAME (default
# postgres). OVERWRITE pg_hba.conf (Debian's default `local all all peer` is first-match, so
# an appended trust rule never applies).
RUN PG_VERSION=$(ls /etc/postgresql) \
 && printf 'local all all trust\nhost all all 127.0.0.1/32 trust\nhost all all ::1/128 trust\nhost all all 0.0.0.0/0 trust\n' > "/etc/postgresql/${PG_VERSION}/main/pg_hba.conf" \
 && echo "listen_addresses='*'" >> "/etc/postgresql/${PG_VERSION}/main/postgresql.conf"

USER root

# --- Playwright + Chromium, for driving the app in a real browser -------------
# Self-contained under /opt — the member's own runtime is untouched.
ENV PLAYWRIGHT_BROWSERS_PATH=/opt/ms-playwright
RUN apt-get update -qq \
    && apt-get install -y -qq --no-install-recommends \
       xz-utils \
       libxcomposite1 \
       libxdamage1 \
       libxfixes3 \
       libxrandr2 \
       libasound2 \
       libatk1.0-0 \
       libatk-bridge2.0-0 \
       libatspi2.0-0 \
       libcups2 \
       libdbus-1-3 \
       libgbm1 \
       libnspr4 \
       libnss3 \
       libxkbcommon0 \
       libpango-1.0-0 \
       libcairo2 \
       libxshmfence1 \
       libx11-xcb1 \
       libxcb-dri3-0 \
       libdrm2 \
    && rm -rf /var/lib/apt/lists/*
RUN set -eux; \
    arch="$(dpkg --print-architecture)"; \
    case "$arch" in amd64) nodearch=x64;; arm64) nodearch=arm64;; *) echo "unsupported arch: $arch" >&2; exit 1;; esac; \
    curl -fsSL "https://nodejs.org/dist/v20.19.5/node-v20.19.5-linux-${nodearch}.tar.xz" -o /tmp/pw-node.tar.xz; \
    mkdir -p /opt/pw-node; \
    tar -xJf /tmp/pw-node.tar.xz -C /opt/pw-node --strip-components=1; \
    rm /tmp/pw-node.tar.xz; \
    export npm_config_prefix=/opt/pw-node PATH="/opt/pw-node/bin:$PATH"; \
    /opt/pw-node/bin/npm install -g playwright@1.56.0; \
    test -d /opt/pw-node/lib/node_modules/playwright; \
    /opt/pw-node/bin/node /opt/pw-node/lib/node_modules/playwright/cli.js install chromium

# `pw <script.js>` runs Node with `require("playwright")` resolvable (CommonJS).
RUN printf '#!/bin/sh\nNODE_PATH=/opt/pw-node/lib/node_modules exec /opt/pw-node/bin/node "$@"\n' > /usr/local/bin/pw \
    && chmod +x /usr/local/bin/pw

# Fail the build if Chromium cannot start.
RUN printf 'const{chromium}=require("playwright");(async()=>{const b=await chromium.launch();const p=await b.newPage();await p.setContent("<h1 id=t>ok</h1>");if(await p.textContent("#t")!=="ok")throw new Error("bad render");await b.close();console.log("chromium OK");})()\n' > /tmp/pw-check.js \
    && pw /tmp/pw-check.js \
    && rm -f /tmp/pw-check.js
# `ember test` resolves its browser via CHROME_BIN, falling back to `google-chrome` on PATH
# (frontend/testem.js). Point both at the Chromium Playwright just installed. The glob is
# resolved at build time so a Playwright bump can't strand a hardcoded chromium-<build> path.
RUN set -eux; \
    chrome="$(echo /opt/ms-playwright/chromium-*/chrome-linux/chrome)"; \
    test -x "$chrome"; \
    printf '#!/bin/bash\nexec %s --no-sandbox --disable-dev-shm-usage "$@"\n' "$chrome" \
      > /usr/local/bin/google-chrome; \
    chmod +x /usr/local/bin/google-chrome; \
    google-chrome --version
ENV CHROME_BIN=/usr/local/bin/google-chrome

ENV IS_SANDBOX=1
RUN mkdir -p /root/.claude && \
    echo '{"permissions":{"deny":["WebFetch","WebSearch"]}}' > /root/.claude/settings.json

# Startup for a direct `docker run` (the devcontainer path uses post-start.sh instead, which
# starts the same services). Bring up Postgres + Redis + MongoDB, then hand off.
RUN cat > /usr/local/bin/start-services.sh <<'EOF'
#!/bin/bash
set -e
service postgresql start || true
service redis-server start >/dev/null 2>&1 || redis-server --daemonize yes >/dev/null 2>&1 || true
mkdir -p /data/db
mongod --dbpath /data/db --bind_ip 127.0.0.1 --fork --logpath /tmp/mongod.log >/dev/null 2>&1 || true
until pg_isready -h localhost -p 5432 -U postgres >/dev/null 2>&1; do sleep 0.5; done
exec "$@"
EOF
RUN chmod +x /usr/local/bin/start-services.sh

WORKDIR /workspace/repo
# Resolver for the DNS jail (.devcontainer/dns-jail-container.sh, applied by
# post-start.sh); if this does not land, Explore just runs unjailed.
RUN (command -v apk >/dev/null 2>&1 && apk add --no-cache dnsmasq bind-tools) \
    || (apt-get update && apt-get install -y --no-install-recommends dnsmasq-base dnsutils \
        && rm -rf /var/lib/apt/lists/*) \
    || true

ENTRYPOINT ["/usr/local/bin/start-services.sh"]
CMD ["sleep", "infinity"]
