# syntax=docker/dockerfile:1.7
# =============================================================================
# Stage 1 — builder: resolve dependencies into a /app/.venv with uv
# =============================================================================
FROM python:3.11-slim-bookworm AS builder

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1 \
    UV_LINK_MODE=copy \
    UV_COMPILE_BYTECODE=1 \
    UV_PYTHON_DOWNLOADS=never

# Install uv from the official Astral image (pinned).
COPY --from=ghcr.io/astral-sh/uv:0.5.4 /uv /uvx /usr/local/bin/

WORKDIR /app

# Cache dependency layer: copy only the manifests first.
COPY pyproject.toml uv.lock* ./

# Sync into /app/.venv. --frozen requires uv.lock; if absent, fall back.
RUN --mount=type=cache,target=/root/.cache/uv \
    if [ -f uv.lock ]; then \
        uv sync --frozen --no-install-project --no-dev; \
    else \
        uv sync --no-install-project --no-dev; \
    fi

# Now copy source and install the project itself.
COPY src ./src
COPY README.md ./README.md
RUN --mount=type=cache,target=/root/.cache/uv \
    uv sync --no-dev

# =============================================================================
# Stage 2 — runtime: minimal image with only the prepared venv + source
# =============================================================================
FROM python:3.11-slim-bookworm AS runtime

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1 \
    PATH="/app/.venv/bin:$PATH"

# Runtime deps: curl for healthchecks, ca-certs for HTTPS, unzip to
# unpack the ProjectDiscovery binaries from their GitHub releases.
RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        ca-certificates \
        curl \
        unzip \
    && rm -rf /var/lib/apt/lists/*

# ProjectDiscovery binaries — pinned releases pulled from GitHub. Both
# get installed under /usr/local/bin/, but `httpx` is renamed to
# `httpx-pd` to avoid the classic clash with the Python `httpx`
# library's CLI (also on PATH from our venv). `fly.toml` overrides
# `SUBSIFT_HTTPX_BIN` and `SUBSIFT_SUBFINDER_BIN` to point here.
ARG SUBFINDER_VERSION=2.6.6
ARG HTTPX_VERSION=1.6.9
ARG TARGETARCH=amd64
RUN set -eux; \
    curl -sSL "https://github.com/projectdiscovery/subfinder/releases/download/v${SUBFINDER_VERSION}/subfinder_${SUBFINDER_VERSION}_linux_${TARGETARCH}.zip" -o /tmp/subfinder.zip; \
    unzip -j /tmp/subfinder.zip subfinder -d /usr/local/bin/; \
    chmod +x /usr/local/bin/subfinder; \
    rm /tmp/subfinder.zip; \
    curl -sSL "https://github.com/projectdiscovery/httpx/releases/download/v${HTTPX_VERSION}/httpx_${HTTPX_VERSION}_linux_${TARGETARCH}.zip" -o /tmp/httpx.zip; \
    unzip -j /tmp/httpx.zip httpx -d /tmp/; \
    mv /tmp/httpx /usr/local/bin/httpx-pd; \
    chmod +x /usr/local/bin/httpx-pd; \
    rm /tmp/httpx.zip; \
    /usr/local/bin/subfinder -version; \
    /usr/local/bin/httpx-pd -version

# Non-root user.
RUN groupadd --system --gid 1000 subsift \
    && useradd --system --uid 1000 --gid subsift --create-home subsift

WORKDIR /app

COPY --from=builder --chown=subsift:subsift /app/.venv /app/.venv
COPY --from=builder --chown=subsift:subsift /app/src /app/src
COPY --chown=subsift:subsift pyproject.toml README.md alembic.ini ./
# Alembic migrations — required for the `alembic upgrade head` release
# command on Fly.io. Without these the release VM dies with
# `No 'script_location' key found in configuration.` and the deploy
# aborts before any traffic routes.
COPY --chown=subsift:subsift migrations /app/migrations

# Pre-create the SQLite data dir so the non-root user can write to it.
# The default DB URL is `sqlite+aiosqlite:///./data/subsift.db` (see
# subsift/config.py), so /app/data must exist and be writable at runtime.
RUN mkdir -p /app/data /app/data/screenshots \
    && chown -R subsift:subsift /app/data

USER subsift

EXPOSE 8000

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

# Run Alembic on the same machine as uvicorn so migrations land on the
# mounted volume. Fly.io's release_command runs on an ephemeral VM that
# does NOT mount our persistent `subsift_data` volume, so any tables it
# creates get thrown away — see fly.toml for the matching comment.
CMD ["sh", "-c", "alembic upgrade head && uvicorn subsift.api.main:app --host 0.0.0.0 --port 8000"]
