# Production Docker Compose - Uses pre-built images from Gitea Packages
#
# Prerequisites:
#   - Images built and pushed to git.mosaicstack.dev/mosaic/*
#   - .env file configured with production values
#
# Usage:
#   docker compose -f docker-compose.prod.yml up -d
#
# For Portainer:
#   - Stack → Add Stack → Repository
#   - Compose file: docker-compose.prod.yml

services:
  # ======================
  # PostgreSQL Database
  # ======================
  postgres:
    image: git.mosaicstack.dev/mosaic/stack-postgres:${IMAGE_TAG:-latest}
    container_name: mosaic-postgres
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${POSTGRES_USER:-mosaic}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB:-mosaic}
      POSTGRES_SHARED_BUFFERS: ${POSTGRES_SHARED_BUFFERS:-256MB}
      POSTGRES_EFFECTIVE_CACHE_SIZE: ${POSTGRES_EFFECTIVE_CACHE_SIZE:-1GB}
      POSTGRES_MAX_CONNECTIONS: ${POSTGRES_MAX_CONNECTIONS:-100}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-mosaic} -d ${POSTGRES_DB:-mosaic}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    networks:
      - mosaic-internal
    labels:
      - "com.mosaic.service=database"
      - "com.mosaic.description=PostgreSQL 17 with pgvector"

  # ======================
  # Valkey Cache
  # ======================
  valkey:
    image: valkey/valkey:8-alpine
    container_name: mosaic-valkey
    restart: unless-stopped
    command:
      - valkey-server
      - --maxmemory ${VALKEY_MAXMEMORY:-256mb}
      - --maxmemory-policy noeviction
      - --appendonly yes
    volumes:
      - valkey_data:/data
    healthcheck:
      test: ["CMD", "valkey-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s
    networks:
      - mosaic-internal
    labels:
      - "com.mosaic.service=cache"
      - "com.mosaic.description=Valkey Redis-compatible cache"

  # ======================
  # Mosaic API
  # ======================
  api:
    image: git.mosaicstack.dev/mosaic/stack-api:${IMAGE_TAG:-latest}
    container_name: mosaic-api
    restart: unless-stopped
    environment:
      NODE_ENV: production
      PORT: ${API_PORT:-3001}
      API_HOST: ${API_HOST:-0.0.0.0}
      DATABASE_URL: postgresql://${POSTGRES_USER:-mosaic}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-mosaic}
      VALKEY_URL: redis://valkey:6379
      OIDC_ISSUER: ${OIDC_ISSUER}
      OIDC_CLIENT_ID: ${OIDC_CLIENT_ID}
      OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET}
      OIDC_REDIRECT_URI: ${OIDC_REDIRECT_URI}
      JWT_SECRET: ${JWT_SECRET}
      JWT_EXPIRATION: ${JWT_EXPIRATION:-24h}
      BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
      OLLAMA_ENDPOINT: ${OLLAMA_ENDPOINT:-http://ollama:11434}
    ports:
      - "${API_PORT:-3001}:${API_PORT:-3001}"
    depends_on:
      postgres:
        condition: service_healthy
      valkey:
        condition: service_healthy
    healthcheck:
      test:
        [
          "CMD-SHELL",
          'node -e "require(''http'').get(''http://localhost:${API_PORT:-3001}/health'', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"',
        ]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    networks:
      - mosaic-internal
      - mosaic-public
    labels:
      - "com.mosaic.service=api"
      - "com.mosaic.description=Mosaic NestJS API"
      - "traefik.enable=${TRAEFIK_ENABLE:-false}"
      - "traefik.http.routers.mosaic-api.rule=Host(`${MOSAIC_API_DOMAIN:-api.mosaicstack.dev}`)"
      - "traefik.http.routers.mosaic-api.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}"
      - "traefik.http.routers.mosaic-api.tls=${TRAEFIK_TLS_ENABLED:-true}"
      - "traefik.http.services.mosaic-api.loadbalancer.server.port=${API_PORT:-3001}"
      - "traefik.docker.network=${TRAEFIK_DOCKER_NETWORK:-mosaic-public}"
      - "traefik.http.routers.mosaic-api.tls.certresolver=${TRAEFIK_CERTRESOLVER:-}"

  # ======================
  # Mosaic Web
  # ======================
  web:
    image: git.mosaicstack.dev/mosaic/stack-web:${IMAGE_TAG:-latest}
    container_name: mosaic-web
    restart: unless-stopped
    environment:
      NODE_ENV: production
      PORT: ${WEB_PORT:-3000}
      NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-https://api.mosaicstack.dev}
    ports:
      - "${WEB_PORT:-3000}:${WEB_PORT:-3000}"
    depends_on:
      api:
        condition: service_healthy
    healthcheck:
      test:
        [
          "CMD-SHELL",
          'node -e "require(''http'').get(''http://localhost:${WEB_PORT:-3000}'', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"',
        ]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    networks:
      - mosaic-public
    labels:
      - "com.mosaic.service=web"
      - "com.mosaic.description=Mosaic Next.js Web App"
      - "traefik.enable=${TRAEFIK_ENABLE:-false}"
      - "traefik.http.routers.mosaic-web.rule=Host(`${MOSAIC_WEB_DOMAIN:-app.mosaicstack.dev}`)"
      - "traefik.http.routers.mosaic-web.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}"
      - "traefik.http.routers.mosaic-web.tls=${TRAEFIK_TLS_ENABLED:-true}"
      - "traefik.http.services.mosaic-web.loadbalancer.server.port=${WEB_PORT:-3000}"
      - "traefik.docker.network=${TRAEFIK_DOCKER_NETWORK:-mosaic-public}"
      - "traefik.http.routers.mosaic-web.tls.certresolver=${TRAEFIK_CERTRESOLVER:-}"

# ======================
# Volumes
# ======================
volumes:
  postgres_data:
    name: mosaic-postgres-data
    driver: local
  valkey_data:
    name: mosaic-valkey-data
    driver: local

# ======================
# Networks
# ======================
networks:
  mosaic-internal:
    name: mosaic-internal
    driver: bridge
  mosaic-public:
    name: mosaic-public
    driver: bridge
