# syntax=docker/dockerfile:1

###############################################################################
# Base
#
# Both stages share it, so dependencies are resolved against exactly the PHP
# that will run them — Filament requires ext-intl, and a composer image that
# lacks it would either refuse to install or, worse, install something the
# runtime cannot use.
###############################################################################
# PHP 8.4, not the 8.3 that composer.json's `^8.3` suggests: the lock file
# resolved Symfony 8, which requires >=8.4.1. Building on 8.3 fails at
# `composer install`, which is a much better place to find out than a deploy.
FROM dunglas/frankenphp:1-php8.4 AS base

WORKDIR /app

# gd with WebP is not optional: it is what App\Services\Media\ImageProcessor
# derives every responsive version with. exif is what stops a photo taken
# sideways staying sideways. pcntl lets the queue worker shut down cleanly
# instead of being killed mid-job.
RUN install-php-extensions \
        pdo_pgsql \
        gd \
        exif \
        intl \
        zip \
        pcntl \
        opcache \
    && apt-get update \
    && apt-get install -y --no-install-recommends postgresql-client \
    && rm -rf /var/lib/apt/lists/*

# In base rather than only in runtime, so the test stage runs under the same
# PHP settings production does — a memory limit that is only set in production
# is a memory limit nothing has tried.
COPY docker/php.ini /usr/local/etc/php/conf.d/app.ini

###############################################################################
# Dependencies
###############################################################################
FROM base AS vendor

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

COPY composer.json composer.lock ./

# `--no-scripts` because the post-install hooks boot the application, and the
# application cannot boot before its code is here. They are run explicitly in
# the runtime stage instead, where everything exists.
RUN composer install \
        --no-dev \
        --no-scripts \
        --no-autoloader \
        --prefer-dist \
        --no-interaction

COPY . .

RUN composer dump-autoload --no-dev --optimize --classmap-authoritative

###############################################################################
# Test
#
# The production image is built with --no-dev, which leaves out the test runner
# itself. Verifying this application against Postgres therefore needs its own
# stage — see docker-compose.test.yml, and the JSON-column queries it exists to
# exercise.
###############################################################################
FROM base AS test

# Only the dev dependencies need this one, so production stays without it.
RUN install-php-extensions bcmath

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

COPY composer.json composer.lock ./

RUN composer install --no-scripts --no-autoloader --prefer-dist --no-interaction

COPY . .

# An empty .env: the file is excluded from the build context on purpose, and
# without it every single test emits a "failed to open stream" warning that
# buries the real output.
RUN touch .env \
    && composer dump-autoload --optimize \
    && php artisan package:discover --ansi

###############################################################################
# Runtime
###############################################################################
FROM base AS runtime

LABEL org.opencontainers.image.title="Pireon Admin" \
      org.opencontainers.image.description="Admin panel and REST API for the collective"

COPY docker/Caddyfile /etc/caddy/Caddyfile

COPY --from=vendor /app/vendor ./vendor
COPY . .

COPY docker/entrypoint.sh /usr/local/bin/entrypoint
RUN chmod +x /usr/local/bin/entrypoint

# Filament serves its own CSS and JS from public/; publishing them at build
# time means the running container never writes to public/.
#
# There is deliberately no Node stage: the only `@vite` directive left is in
# Laravel's default welcome page, which this application redirects away from.
RUN php artisan package:discover --ansi \
    && php artisan filament:assets

RUN chown -R www-data:www-data storage bootstrap/cache

ENV SERVER_NAME=:80

EXPOSE 80

ENTRYPOINT ["entrypoint"]

CMD ["frankenphp", "run", "--config", "/etc/caddy/Caddyfile"]
