# #region docker.compose.enterprise-clean [C:4] [TYPE Module] [SEMANTICS docker,compose,enterprise]
# @BRIEF Enterprise docker compose — сборка backend + frontend + agent из исходников, внешний Postgres, корп. сертификаты.
# @PRE Docker и docker compose установлены. Файлы .env.enterprise-clean настроены.
#   Postgres: внешний, доступный по POSTGRES_HOST:POSTGRES_PORT.
#   Сертификаты: опциональные .crt файлы в CERTS_PATH монтируются в /opt/certs.
# @POST Сервисы backend, frontend и agent запущены. SSL терминация в nginx опциональна.
# @SIDE_EFFECT backend использует ENTRYPOINT для установки сертификатов и bootstrap admin.
#   frontend автоопределяет наличие SSL сертификатов и переключает nginx конфиг.
#   agent запускает Gradio-сервер с LangGraph на порту 7860.
# @LAYER Infrastructure
# @RELATION DEPENDS_ON -> [docker/backend.Dockerfile]
# @RELATION DEPENDS_ON -> [docker/frontend.Dockerfile]
# @RELATION DEPENDS_ON -> [docker/Dockerfile.agent]
# @RELATION DEPENDS_ON -> [docker/nginx.conf]
# @RELATION DEPENDS_ON -> [docker/nginx.ssl.conf]
# @RELATION DEPENDS_ON -> [docker/frontend.entrypoint.sh]
# @RELATION DEPENDS_ON -> [docker/backend.entrypoint.sh]
# @DATA_CONTRACT Input: .env.enterprise-clean + ./certs/*.crt -> Output: запущенные контейнеры
# @INVARIANT Внешний Postgres НЕ требует healthcheck внутри compose — ответственность оператора.
#   Backend entrypoint использует wait_for_db() (retry до 30 раз) для проверки доступности БД
#   перед запуском миграций. Если БД недоступна — контейнер exit(1) после таймаута.
# @RATIONALE Нет depends_on для backend → внешний PostgreSQL: оператор гарантирует доступность.
#   wait_for_db() в entrypoint.sh обеспечивает graceful retry вместо мгновенного crash.
# @INVARIANT Если CERTS_PATH пуст или не содержит .crt файлов, entrypoint не падает.
# @INVARIANT nginx слушает порт 80 всегда. Порт 443 включается только если есть server.crt + server.key.
# @RATIONALE Отказ от встроенного postgres-container: корпоративный стандарт — внешний PostgreSQL
#   с TLS, бэкапами и мониторингом на уровне инфраструктуры.
# @RATIONALE Build из исходников вместо pre-built images: предприятие контролирует версии кода
#   и может патчить зависимости. Не подходит для air-gapped — для этого есть bundle:light.
# @REJECTED Использование `image:` + `pull_policy: never` отвергнуто — не работает для сборки
#   из исходников на целевой машине. Гибридный `build: + image:` тоже отвергнут — усложняет
#   логику build.sh и сбивает с толку оператора.

services:
  backend:
    build:
      context: .
      dockerfile: docker/backend.Dockerfile
    restart: unless-stopped
    environment:
      DATABASE_URL: postgresql+psycopg2://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env.enterprise-clean}@${POSTGRES_HOST:?Set POSTGRES_HOST in .env.enterprise-clean}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-ss_tools}
      TASKS_DATABASE_URL: postgresql+psycopg2://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env.enterprise-clean}@${POSTGRES_HOST:?Set POSTGRES_HOST in .env.enterprise-clean}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-ss_tools}
      AUTH_DATABASE_URL: postgresql+psycopg2://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env.enterprise-clean}@${POSTGRES_HOST:?Set POSTGRES_HOST in .env.enterprise-clean}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-ss_tools}
      BACKEND_PORT: 8000
      ENABLE_BELIEF_STATE_LOGGING: ${ENABLE_BELIEF_STATE_LOGGING:-true}
      TASK_LOG_LEVEL: ${TASK_LOG_LEVEL:-INFO}
      INITIAL_ADMIN_CREATE: ${INITIAL_ADMIN_CREATE:-false}
      INITIAL_ADMIN_USERNAME: ${INITIAL_ADMIN_USERNAME:-admin}
      INITIAL_ADMIN_PASSWORD: ${INITIAL_ADMIN_PASSWORD:-}
      INITIAL_ADMIN_EMAIL: ${INITIAL_ADMIN_EMAIL:-}
      OPENAI_API_KEY: ${OPENAI_API_KEY:-}
      ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
      FEATURES__DATASET_REVIEW: ${FEATURES__DATASET_REVIEW:-true}
      FEATURES__HEALTH_MONITOR: ${FEATURES__HEALTH_MONITOR:-true}
      # Путь до сертификатов внутри контейнера — всегда /opt/certs
      CERTS_PATH: /opt/certs
      # URL CA-сертификатов для LLM-провайдеров (скачка на старте, DER→PEM конвертация)
      LLM_CA_CERT_URLS: ${LLM_CA_CERT_URLS:-}
      # Отключить SSL verify для LLM (когда корп. сертификаты не установлены в контейнере)
      LLM_SSL_VERIFY: ${LLM_SSL_VERIFY:-true}
    ports:
      - "${BACKEND_HOST_PORT:-8001}:8000"
    volumes:
      # Единая точка хранения: бэкапы → /app/storage/backups/, git-repos → /app/storage/repositories/, LLM-скриншоты → /app/storage/screenshots/
      - ./storage:/app/storage
      # Корпоративные CA-сертификаты (.crt файлы). Монтируются в /opt/certs,
      # entrypoint.sh установит их в системное хранилище доверия.
      - ${CERTS_PATH:-./certs}:/opt/certs:ro

  frontend:
    build:
      context: .
      dockerfile: docker/frontend.Dockerfile
    restart: unless-stopped
    depends_on:
      - backend
    ports:
      - "${FRONTEND_HOST_PORT:-8000}:80"
      # Если в CERTS_PATH есть server.crt + server.key — nginx включит HTTPS на 443.
      # Если cert-файлов нет — порт 443 не открывается, entrypoint использует HTTP-only конфиг.
      - "${FRONTEND_SSL_PORT:-443}:443"
    volumes:
      # Для frontend тоже можно смонтировать сертификаты — nginx entrypoint
      # автоматически установит CA-сертификаты в Alpine и переключит SSL конфиг.
      - ${CERTS_PATH:-./certs}:/opt/certs:ro

  agent:
    build:
      context: .
      dockerfile: docker/Dockerfile.agent
    restart: unless-stopped
    depends_on:
      - backend
    environment:
      LLM_API_KEY: ${LLM_API_KEY:-}
      LLM_BASE_URL: ${LLM_BASE_URL:-https://api.openai.com/v1}
      LLM_MODEL: ${LLM_MODEL:-gpt-4o}
      FASTAPI_URL: http://backend:8000
      JWT_SECRET: ${JWT_SECRET:-super-secret-key}
      SERVICE_JWT: ${SERVICE_JWT:-agent-service-secret}
      DATABASE_URL: postgresql+psycopg2://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env.enterprise-clean}@${POSTGRES_HOST:?Set POSTGRES_HOST in .env.enterprise-clean}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-ss_tools}
      GRADIO_SERVER_PORT: 7860
    ports:
      - "${AGENT_HOST_PORT:-7860}:7860"

# #endregion docker.compose.enterprise-clean
