# syntax=docker/dockerfile:1

# ============================================================
# Stage 1: Build frontend assets
# ============================================================
FROM node:20-alpine AS frontend

WORKDIR /app

COPY package.json package-lock.json vite.config.js ./
COPY resources/ resources/

RUN npm ci --no-audit --no-fund
RUN npm run build

# ============================================================
# Stage 2: Runtime (FrankenPHP)
# ============================================================
FROM dunglas/frankenphp:1.1-php8.3-alpine AS runtime

RUN apk add --no-cache \
    git \
    postgresql-client \
    curl

RUN install-php-extensions \
    pdo_pgsql \
    redis \
    opcache \
    zip \
    gd \
    intl

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

WORKDIR /app

ENV APP_ENV=production \
    APP_DEBUG=false \
    LOG_CHANNEL=stack \
    LOG_LEVEL=warning \
    DB_CONNECTION=pgsql \
    DB_HOST=db \
    DB_PORT=5432 \
    REDIS_HOST=redis \
    REDIS_PORT=6379 \
    CACHE_STORE=redis \
    QUEUE_CONNECTION=redis \
    SESSION_DRIVER=redis \
    BROADCAST_CONNECTION=log \
    MAIL_MAILER=log

# Copy only the files composer needs before install, so the composer layer stays
# cached when application source changes. packages/ is required because composer.json
# declares it as a path repository.
COPY composer.json composer.lock ./
COPY packages/ packages/

# Skip post-autoload scripts (package:discover) during build — they need a runtime
# Laravel boot which fails without proper env. Discovery happens at runtime via
# start-prod.sh. --classmap-authoritative implies --optimize-autoloader.
RUN composer install --no-dev --no-interaction --prefer-dist --classmap-authoritative --no-scripts

COPY . .
COPY --from=frontend /app/public/build /app/public/build

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

RUN cat > /etc/caddy/Caddyfile <<'EOF'
{
    frankenphp
    order php_server before file_server
}

:8000 {
    root * /app/public

    php_server {
        index index.php
    }

    encode gzip zstd

    file_server

    header {
        X-Frame-Options "SAMEORIGIN"
        X-Content-Type-Options "nosniff"
        Referrer-Policy "strict-origin-when-cross-origin"
    }
}
EOF

EXPOSE 8000

HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
    CMD curl -fsS http://localhost:8000/up || exit 1

RUN cat > /start-prod.sh <<'EOF'
#!/bin/sh
set -e

echo "Waiting for PostgreSQL at ${DB_HOST}:${DB_PORT}..."
for i in $(seq 1 60); do
    if pg_isready -h "${DB_HOST}" -p "${DB_PORT}" -q; then
        echo "PostgreSQL is ready."
        break
    fi
    if [ "$i" = "60" ]; then
        echo "Timed out waiting for PostgreSQL after 60s." >&2
        exit 1
    fi
    sleep 1
done

php artisan package:discover --ansi
php artisan config:cache
php artisan route:cache
php artisan view:cache

php artisan migrate --force

exec frankenphp run --config /etc/caddy/Caddyfile
EOF

RUN chmod +x /start-prod.sh

CMD ["/start-prod.sh"]
