# Kadence — one image that serves the API and the web UI.
#
# Stage 1 builds the React/Material front end; stage 2 installs the Python
# backend and copies those built files into `static/`, which FastAPI serves from
# the same origin. One container, one port, no CORS to configure.

# ---- stage 1: the web UI ---------------------------------------------------
FROM node:22-alpine AS web

WORKDIR /web
COPY frontend/package.json frontend/package-lock.json* ./
RUN npm ci --no-audit --no-fund || npm install --no-audit --no-fund

COPY frontend/ ./
RUN npm run build


# ---- stage 2: the backend --------------------------------------------------
FROM python:3.12-slim AS runtime

ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    PIP_NO_CACHE_DIR=1 \
    TZ=Europe/Moscow

WORKDIR /app

# Build deps for psycopg are already covered by the binary wheel; curl is here
# for the healthcheck only.
RUN apt-get update \
    && apt-get install -y --no-install-recommends curl tzdata \
    && rm -rf /var/lib/apt/lists/*

COPY backend/pyproject.toml ./
COPY backend/app ./app
RUN pip install --no-cache-dir \
        "fastapi>=0.115" "uvicorn[standard]>=0.30" "sqlalchemy>=2.0" \
        "psycopg[binary]>=3.2" "pydantic>=2.8" "pydantic-settings>=2.4" \
        "httpx>=0.27" "beautifulsoup4>=4.12" "apscheduler>=3.10,<4" \
        "python-dotenv>=1.0" "tzdata>=2024.1"

COPY --from=web /web/dist ./static

# The app writes nothing outside the database, so it can run unprivileged.
RUN useradd --create-home --uid 10001 kadence && chown -R kadence:kadence /app
USER kadence

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

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
