# DXA Quality Assessment — контейнер для инференса (CPU)
#
# Сборка:  docker build -t dxa-quality .
# Запуск:  docker run -v /path/to/data:/data -p 8000:8000 dxa-quality
#
# Требования методики: зависимости с зафиксированными версиями и запуск
# локально без обращения к внешним сервисам. Inference не использует
# предобученные веса из интернета — они уже внутри чекпоинта, поэтому
# при запуске сеть не нужна.
FROM python:3.11-slim

# libgl1/libglib2.0-0 нужны opencv (импортируется через зависимости проекта),
# libgomp1 — для параллельных циклов torch.
RUN apt-get update && apt-get install -y --no-install-recommends \
    libgl1 \
    libglib2.0-0 \
    libgomp1 \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# --- Слой зависимостей: отдельно от кода, чтобы кэшировался ---
# Все версии зафиксированы, torch ставится с CPU-индексом: образ для инференса
# не требует GPU, а версия из PyPI на Linux подтянула бы CUDA-колёса.
COPY requirements.txt ./
RUN pip install --no-cache-dir --upgrade pip \
    && pip install --no-cache-dir \
        --extra-index-url https://download.pytorch.org/whl/cpu \
        -r requirements.txt

# --- Код ---
COPY src ./src
COPY models ./models

# Скрипт пакетной обработки (оценка берёт его из корня образа).
COPY run.sh ./run.sh
RUN chmod +x ./run.sh

# smoke-проверка: чекпоинт должен читаться. Падает на сборке, если модели нет,
# вместо тихого 500 на каждом запросе в рантайме.
RUN python -c "import os, torch; p='models/dxa_model.pth'; \
    assert os.path.exists(p), f'missing checkpoint {p}'; \
    ck=torch.load(p, map_location='cpu', weights_only=False); \
    assert 'model_state_dict' in ck, 'checkpoint has no model_state_dict'; \
    print('checkpoint ok:', ck.get('backbone'), ck.get('head'))"

# --- Сборка статики для офлайн-работы ---
# Веб-интерфейс не должен зависеть от CDN: Tailwind и FontAwesome лежат в
# src/api/static/vendor и src/api/static/webfonts (см. index.html). Сборка
# проверяет их наличие, чтобы образ не остался без оформления.
RUN python -c "import os; \
    files=['src/api/static/vendor/tailwind.js','src/api/static/vendor/fontawesome.css', \
           'src/api/static/webfonts/fa-solid-900.woff2']; \
    missing=[f for f in files if not os.path.exists(f)]; \
    assert not missing, f'missing frontend assets: {missing}'; \
    print('frontend assets ok')"

ENV PYTHONUNBUFFERED=1 \
    PYTHONPATH=/app \
    DXA_MODEL_PATH=/app/models/dxa_model.pth

EXPOSE 8000

# HEALTHCHECK опирается на /api/v1/health, который отдаёт model_loaded.
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
    CMD python -c "import urllib.request,sys; \
        r=urllib.request.urlopen('http://127.0.0.1:8000/api/v1/health', timeout=5); \
        sys.exit(0 if r.status==200 else 1)"

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