# --- Stage 1: compile Tailwind CSS + vendor JS deps ----------------------
# Runs the Tailwind JIT over views/, src/, and our JS so only classes that
# are actually referenced end up in the output. No runtime <style> injection,
# which lets the CSP drop 'unsafe-inline' for style-src.
#
# The same stage also vendors Alpine.js (CSP build), htmx, and SortableJS
# from npm into /build/vendor/ — copied into the runtime image alongside the
# CSS so the strict CSP can keep `script-src 'self'`.
FROM node:20-alpine AS css-builder

WORKDIR /build
COPY package.json package-lock.json* ./
RUN npm ci --no-audit --no-fund

# Only the files that contribute to class discovery / the entry stylesheet.
COPY tailwind.config.js ./
COPY assets/css/input.css ./assets/css/input.css
COPY views/ ./views/
COPY src/ ./src/
COPY public/assets/js/ ./public/assets/js/

RUN npx tailwindcss -i ./assets/css/input.css -o /build/app.css --minify

# Pin the vendored JS bundles. Alpine CSP is the variant that doesn't need
# `unsafe-eval`; standard Alpine would require relaxing the CSP.
RUN mkdir -p /build/vendor \
    && cp node_modules/@alpinejs/csp/dist/cdn.min.js /build/vendor/alpine-csp.min.js \
    && cp node_modules/htmx.org/dist/htmx.min.js     /build/vendor/htmx.min.js \
    && cp node_modules/sortablejs/Sortable.min.js    /build/vendor/sortable.min.js

# --- Stage 2: tailwind --watch (dev only) -------------------------------
# Used by docker-compose.dev.yml. Source dirs are bind-mounted from the
# host at /build/* and `app.css` is regenerated on save. Vendor JS bundles
# are seeded into the host-mounted public/assets/js/vendor on first start
# by bin/dev-css-watcher.sh — they don't change between iterations so a
# single seed at startup is enough.
FROM node:20-alpine AS css-watcher
WORKDIR /build
COPY package.json package-lock.json* ./
RUN npm ci --no-audit --no-fund
COPY bin/dev-css-watcher.sh /usr/local/bin/dev-css-watcher.sh
RUN chmod +x /usr/local/bin/dev-css-watcher.sh
CMD ["/usr/local/bin/dev-css-watcher.sh"]

# --- Stage 3: the actual PHP runtime ------------------------------------
FROM php:8.3-apache AS runtime

RUN apt-get update && apt-get install -y --no-install-recommends \
        libsqlite3-dev libzip-dev libpng-dev libjpeg-dev libfreetype6-dev unzip git \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install pdo pdo_sqlite zip gd \
    && a2enmod rewrite \
    && rm -rf /var/lib/apt/lists/*

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html

COPY composer.json composer.lock* ./
RUN composer install --no-dev --no-interaction --prefer-dist --no-progress

COPY . .

# Place the compiled CSS + vendored JS where Apache can serve them.
COPY --from=css-builder /build/app.css     /var/www/html/public/assets/css/app.css
COPY --from=css-builder /build/vendor/     /var/www/html/public/assets/js/vendor/

# Twig cache lives under data/ alongside the SQLite file. www-data must be
# able to write there at request time so first-render template compilation
# succeeds.
RUN mkdir -p /var/www/data /var/www/data/sessions /var/www/html/data/twig-cache \
    && chown -R www-data:www-data /var/www/data /var/www/html/data \
    && printf '%s\n' \
        '<VirtualHost *:80>' \
        '    DocumentRoot /var/www/html/public' \
        '    <Directory /var/www/html/public>' \
        '        Options -Indexes +FollowSymLinks' \
        '        AllowOverride All' \
        '        Require all granted' \
        '        FallbackResource /index.php' \
        '    </Directory>' \
        '    ErrorLog ${APACHE_LOG_DIR}/error.log' \
        '    CustomLog ${APACHE_LOG_DIR}/access.log combined' \
        '</VirtualHost>' \
        > /etc/apache2/sites-available/000-default.conf

# R01-N22: run migrations at container start, before Apache binds the port.
# The request path no longer auto-migrates — it only checks and refuses to
# serve when something is pending — so a missed entrypoint produces a loud
# 503, not silent stale-schema serving.
RUN install -m 0755 /var/www/html/bin/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh

EXPOSE 80
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["apache2-foreground"]

# --- Stage 4: phpunit + dev composer deps (test runner) -----------------
# Built on top of `runtime` so the test environment matches prod exactly,
# then layers in the composer dev dependencies (phpunit, mocks). Used by
# `make test` / `make check` via `docker compose run --rm tests`.
# Inherits the entrypoint, which runs migrations against an in-container
# SQLite before phpunit starts — tests get a fresh, fully-migrated schema.
FROM runtime AS tests
RUN composer install --no-interaction --prefer-dist --no-progress
CMD ["composer", "test"]
