# ============================================================
# OmniCommerce Cloud — Production Docker Compose
# Multi-environment: dev, staging, production
# ============================================================

version: "3.9"

x-common-env: &common-env
  TZ: UTC
  ENVIRONMENT: ${ENVIRONMENT:-production}
  LOG_LEVEL: ${LOG_LEVEL:-info}

x-postgres-env: &postgres-env
  POSTGRES_DB: ${POSTGRES_DB:-omnicommerce}
  POSTGRES_USER: ${POSTGRES_USER:-omni}
  POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
  POSTGRES_HOST_AUTH_METHOD: scram-sha-256

# ============================================================
# NETWORKS
# ============================================================
networks:
  internal:
    driver: bridge
    internal: true
    ipam:
      config:
        - subnet: 10.10.0.0/16
  public:
    driver: bridge
    ipam:
      config:
        - subnet: 10.20.0.0/16
  monitoring:
    driver: bridge
    internal: true

# ============================================================
# VOLUMES
# ============================================================
volumes:
  postgres_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /data/postgres
  postgres_backup:
  redis_data:
  es_data:
  kafka_data:
  zk_data:
  minio_data:
  grafana_data:
  prometheus_data:
  loki_data:
  temporal_data:
  redisinsight_data:

# ============================================================
# SECRETS
# ============================================================
secrets:
  db_password:
    file: ./secrets/db_password.txt
  jwt_secret:
    file: ./secrets/jwt_secret.txt
  stripe_secret:
    file: ./secrets/stripe_secret.txt
  minio_secret:
    file: ./secrets/minio_secret.txt
  redis_password:
    file: ./secrets/redis_password.txt

# ============================================================
# SERVICES
# ============================================================

services:
  # ==================== DATABASES ====================

  postgres:
    image: postgres:16.3-alpine
    container_name: omnicommerce-db
    restart: unless-stopped
    networks:
      - internal
    environment:
      <<: [*postgres-env, *common-env]
    ports:
      - "${POSTGRES_PORT:-5432}:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - postgres_backup:/backups
      - ../database/migrations:/docker-entrypoint-initdb.d:ro
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-omni} -d ${POSTGRES_DB:-omnicommerce}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    deploy:
      resources:
        limits:
          cpus: '4'
          memory: 8G
        reservations:
          cpus: '2'
          memory: 4G
    command: >
      postgres
      -c shared_buffers=2GB
      -c effective_cache_size=6GB
      -c maintenance_work_mem=512MB
      -c checkpoint_completion_target=0.9
      -c wal_buffers=16MB
      -c default_statistics_target=100
      -c random_page_cost=1.1
      -c effective_io_concurrency=200
      -c work_mem=5242kB
      -c min_wal_size=1GB
      -c max_wal_size=4GB
      -c max_worker_processes=8
      -c max_parallel_workers_per_gather=4
      -c max_parallel_workers=8
      -c max_parallel_maintenance_workers=4
      -c max_connections=200
      -c ssl=on
      -c ssl_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
      -c ssl_key_file=/etc/ssl/private/ssl-cert-snakeoil.key

  postgres-backup:
    image: prodrigestivill/postgres-backup-local:16
    container_name: omnicommerce-db-backup
    restart: unless-stopped
    networks:
      - internal
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      POSTGRES_HOST: postgres
      POSTGRES_DB: ${POSTGRES_DB:-omnicommerce}
      POSTGRES_USER: ${POSTGRES_USER:-omni}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_EXTRA_OPTS: '--schema=public --blobs'
      SCHEDULE: '@every 6h'
      BACKUP_KEEP_DAYS: 30
      BACKUP_KEEP_WEEKS: 12
      BACKUP_KEEP_MONTHS: 12
      HEALTHCHECK_PORT: 8080
    volumes:
      - postgres_backup:/backups

  # ==================== REDIS ====================

  redis:
    image: redis:7.2-alpine
    container_name: omnicommerce-cache
    restart: unless-stopped
    networks:
      - internal
    command: >
      redis-server
      --appendonly yes
      --maxmemory 4gb
      --maxmemory-policy allkeys-lru
      --requirepass ${REDIS_PASSWORD}
      --save 900 1
      --save 300 10
      --save 60 10000
      --tls-port 6379
      --tls-cert-file /tls/redis.crt
      --tls-key-file /tls/redis.key
      --tls-ca-cert-file /tls/ca.crt
    ports:
      - "${REDIS_PORT:-6379}:6379"
    volumes:
      - redis_data:/data
      - ./certs:/tls:ro
    healthcheck:
      test: ["CMD", "redis-cli", "--no-auth-warning", "-a", "${REDIS_PASSWORD}", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 6G

  redis-sentinel:
    image: redis:7.2-alpine
    container_name: omnicommerce-sentinel
    restart: unless-stopped
    networks:
      - internal
    command: >
      redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./redis-sentinel.conf:/etc/redis/sentinel.conf:ro
    depends_on:
      redis:
        condition: service_healthy
    ports:
      - "26379:26379"
    profiles: [production]

  # ==================== ELASTICSEARCH ====================

  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.13.0
    container_name: omnicommerce-search
    restart: unless-stopped
    networks:
      - internal
    environment:
      - node.name=${ES_NODE_NAME:-es01}
      - cluster.name=omnicommerce-${ENVIRONMENT:-production}
      - discovery.type=${ES_DISCOVERY:-single-node}
      - discovery.seed_hosts=${ES_SEED_HOSTS:-}
      - cluster.initial_master_nodes=${ES_MASTER_NODES:-es01}
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms2g -Xmx2g -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError"
      - xpack.security.enabled=${ES_SECURITY_ENABLED:-true}
      - xpack.security.transport.ssl.enabled=true
      - xpack.security.transport.ssl.verification_mode=certificate
      - xpack.security.transport.ssl.keystore.path=/usr/share/elasticsearch/config/certs/elastic-certificates.p12
      - xpack.security.transport.ssl.truststore.path=/usr/share/elasticsearch/config/certs/elastic-certificates.p12
      - xpack.security.http.ssl.enabled=${ES_SECURITY_ENABLED:-true}
      - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
    ports:
      - "${ES_HTTP_PORT:-9200}:9200"
      - "${ES_TRANSPORT_PORT:-9300}:9300"
    volumes:
      - es_data:/usr/share/elasticsearch/data
      - ./elasticsearch/certs:/usr/share/elasticsearch/config/certs:ro
    healthcheck:
      test: ["CMD-SHELL", "curl -s -u elastic:${ELASTIC_PASSWORD} https://localhost:9200/_cluster/health | grep -q 'green\|yellow'"]
      interval: 30s
      timeout: 10s
      retries: 10
      start_period: 120s
    deploy:
      resources:
        limits:
          cpus: '4'
          memory: 8G
        reservations:
          cpus: '2'
          memory: 4G
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65536
        hard: 65536

  kibana:
    image: docker.elastic.co/kibana/kibana:8.13.0
    container_name: omnicommerce-kibana
    restart: unless-stopped
    networks:
      - internal
      - monitoring
    environment:
      - ELASTICSEARCH_HOSTS=https://elasticsearch:9200
      - ELASTICSEARCH_USERNAME=kibana_system
      - ELASTICSEARCH_PASSWORD=${KIBANA_PASSWORD}
      - ELASTICSEARCH_SSL_VERIFICATIONMODE=certificate
      - SERVER_PUBLICBASEURL=https://kibana.${DOMAIN:-omnicommerce.io}
    ports:
      - "${KIBANA_PORT:-5601}:5601"
    depends_on:
      elasticsearch:
        condition: service_healthy
    profiles: [production]

  # ==================== KAFKA ====================

  zookeeper:
    image: confluentinc/cp-zookeeper:7.6.0
    container_name: omnicommerce-zk
    restart: unless-stopped
    networks:
      - internal
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000
      ZOOKEEPER_SYNC_LIMIT: 5
      ZOOKEEPER_INIT_LIMIT: 10
      ZOOKEEPER_SERVER_ID: 1
      ZOOKEEPER_SERVERS: zookeeper:2888:3888
    ports:
      - "2181:2181"
    volumes:
      - zk_data:/var/lib/zookeeper/data
      - zk_data:/var/lib/zookeeper/log
    healthcheck:
      test: ["CMD", "echo", "ruok", "|", "nc", "localhost", "2181"]
      interval: 30s
      timeout: 5s
      retries: 5

  kafka:
    image: confluentinc/cp-kafka:7.6.0
    container_name: omnicommerce-kafka
    restart: unless-stopped
    networks:
      - internal
    depends_on:
      zookeeper:
        condition: service_healthy
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT,INTERNAL:PLAINTEXT
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:9093,INTERNAL://kafka:29092
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: ${KAFKA_REPLICATION:-3}
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: ${KAFKA_REPLICATION:-3}
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 2
      KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
      KAFKA_NUM_PARTITIONS: 12
      KAFKA_DEFAULT_REPLICATION_FACTOR: ${KAFKA_REPLICATION:-3}
      KAFKA_LOG_RETENTION_HOURS: 168
      KAFKA_LOG_SEGMENT_BYTES: 1073741824
      KAFKA_LOG_RETENTION_CHECK_INTERVAL_MS: 300000
      KAFKA_COMPRESSION_TYPE: lz4
      KAFKA_MESSAGE_MAX_BYTES: 10485760
    ports:
      - "${KAFKA_PORT:-9093}:9093"
    volumes:
      - kafka_data:/var/lib/kafka/data
    healthcheck:
      test: ["CMD", "kafka-topics", "--bootstrap-server", "kafka:9092", "--list"]
      interval: 30s
      timeout: 10s
      retries: 10
    deploy:
      resources:
        limits:
          cpus: '4'
          memory: 8G

  kafka-ui:
    image: provectuslabs/kafka-ui:latest
    container_name: omnicommerce-kafka-ui
    restart: unless-stopped
    networks:
      - internal
      - monitoring
    environment:
      KAFKA_CLUSTERS_0_NAME: omnicommerce
      KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9092
      KAFKA_CLUSTERS_0_ZOOKEEPER: zookeeper:2181
    ports:
      - "${KAFKA_UI_PORT:-8085}:8080"
    profiles: [dev]

  # ==================== MINIO (S3) ====================

  minio:
    image: minio/minio:RELEASE.2024-06-06T09-36-42Z
    container_name: omnicommerce-storage
    restart: unless-stopped
    networks:
      - internal
      - public
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
      MINIO_BROWSER_REDIRECT_URL: https://minio-console.${DOMAIN:-omnicommerce.io}
      MINIO_SERVER_URL: https://s3.${DOMAIN:-omnicommerce.io}
      MINIO_PROMETHEUS_AUTH_TYPE: public
    ports:
      - "${MINIO_API_PORT:-9000}:9000"
      - "${MINIO_CONSOLE_PORT:-9001}:9001"
    volumes:
      - minio_data:/data
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 30s
    deploy:
      resources:
        limits:
          cpus: '4'
          memory: 8G

  # ==================== TEMPORAL (Workflow Engine) ====================

  temporal:
    image: temporalio/auto-setup:1.24.2
    container_name: omnicommerce-temporal
    restart: unless-stopped
    networks:
      - internal
    depends_on:
      postgres:
        condition: service_healthy
      kafka:
        condition: service_healthy
    environment:
      DB: postgres12
      DB_PORT: 5432
      POSTGRES_USER: ${POSTGRES_USER:-omni}
      POSTGRES_PWD: ${POSTGRES_PASSWORD}
      POSTGRES_SEEDS: postgres
      ENABLE_ES: "true"
      ES_SEEDS: elasticsearch:9200
      ES_VERSION: v8
      DYNAMIC_CONFIG_FILE_PATH: config/dynamicconfig/development.yaml
    ports:
      - "${TEMPORAL_PORT:-7233}:7233"
    volumes:
      - temporal_data:/etc/temporal/config/dynamicconfig
    healthcheck:
      test: ["CMD", "tctl", "--address", "temporal:7233", "cluster", "health"]
      interval: 30s
      timeout: 10s
      retries: 10
    profiles: [production]

  temporal-web:
    image: temporalio/web:2.28.0
    container_name: omnicommerce-temporal-ui
    restart: unless-stopped
    networks:
      - internal
      - monitoring
    environment:
      TEMPORAL_ADDRESS: temporal:7233
      TEMPORAL_CORS_ORIGINS: https://temporal.${DOMAIN:-omnicommerce.io}
    ports:
      - "${TEMPORAL_WEB_PORT:-8088}:8088"
    depends_on:
      temporal:
        condition: service_healthy
    profiles: [production]

  # ==================== MONITORING STACK ====================

  prometheus:
    image: prom/prometheus:v2.52.0
    container_name: omnicommerce-prometheus
    restart: unless-stopped
    networks:
      - monitoring
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=30d'
      - '--web.console.libraries=/usr/share/prometheus/console_libraries'
      - '--web.console.templates=/usr/share/prometheus/consoles'
      - '--web.enable-lifecycle'
      - '--web.enable-admin-api'
    ports:
      - "${PROMETHEUS_PORT:-9090}:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ./prometheus/alerts.yml:/etc/prometheus/alerts.yml:ro
      - prometheus_data:/prometheus
    healthcheck:
      test: ["CMD", "wget", "-q", "--tries=1", "http://localhost:9090/-/healthy"]
      interval: 30s
      timeout: 10s
      retries: 3

  grafana:
    image: grafana/grafana:11.0.0
    container_name: omnicommerce-grafana
    restart: unless-stopped
    networks:
      - monitoring
    environment:
      GF_SECURITY_ADMIN_USER: ${GRAFANA_USER:-admin}
      GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD}
      GF_SERVER_ROOT_URL: https://grafana.${DOMAIN:-omnicommerce.io}
      GF_INSTALL_PLUGINS: grafana-piechart-panel,grafana-worldmap-panel
      GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH: /etc/grafana/dashboards/omnicommerce-overview.json
    ports:
      - "${GRAFANA_PORT:-3003}:3000"
    volumes:
      - grafana_data:/var/lib/grafana
      - ./grafana/dashboards:/etc/grafana/dashboards:ro
      - ./grafana/datasources:/etc/grafana/provisioning/datasources:ro
      - ./grafana/dashboard-providers:/etc/grafana/provisioning/dashboards:ro
    depends_on:
      - prometheus
      - loki

  loki:
    image: grafana/loki:2.9.8
    container_name: omnicommerce-loki
    restart: unless-stopped
    networks:
      - monitoring
    command: -config.file=/etc/loki/local-config.yaml
    ports:
      - "${LOKI_PORT:-3100}:3100"
    volumes:
      - loki_data:/loki
      - ./loki/config.yaml:/etc/loki/local-config.yaml:ro
    healthcheck:
      test: ["CMD", "wget", "-q", "--tries=1", "http://localhost:3100/ready"]
      interval: 30s
      timeout: 10s
      retries: 3

  promtail:
    image: grafana/promtail:2.9.8
    container_name: omnicommerce-promtail
    restart: unless-stopped
    networks:
      - monitoring
    volumes:
      - /var/log:/var/log:ro
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
      - ./promtail/config.yml:/etc/promtail/config.yml:ro
    command: -config.file=/etc/promtail/config.yml
    depends_on:
      loki:
        condition: service_healthy

  # ==================== API & FRONTENDS ====================

  backend:
    build:
      context: ../../backend
      dockerfile: Dockerfile
      target: production
      args:
        APP_VERSION: ${APP_VERSION:-1.0.0}
    image: registry.${DOMAIN:-omnicommerce.io}/omnicommerce-api:${APP_VERSION:-latest}
    container_name: omnicommerce-api
    restart: unless-stopped
    networks:
      - internal
      - public
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      kafka:
        condition: service_healthy
      elasticsearch:
        condition: service_healthy
    environment:
      <<: *common-env
      DATABASE_URL: postgres://${POSTGRES_USER:-omni}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-omnicommerce}?sslmode=require
      DATABASE_MAX_CONNS: "80"
      DATABASE_MIN_CONNS: "10"
      DATABASE_MAX_IDLE_TIME: "30m"
      REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0
      REDIS_CLUSTER_MODE: "false"
      KAFKA_BROKERS: kafka:9092
      ELASTICSEARCH_URL: https://elastic:${ELASTIC_PASSWORD}@elasticsearch:9200
      MINIO_ENDPOINT: minio:9000
      MINIO_ACCESS_KEY: ${MINIO_ROOT_USER}
      MINIO_SECRET_KEY: ${MINIO_ROOT_PASSWORD}
      MINIO_USE_SSL: "false"
      JWT_SECRET: ${JWT_SECRET}
      JWT_EXPIRY: "24h"
      JWT_REFRESH_EXPIRY: "30d"
      STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY}
      STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET}
      SMTP_HOST: ${SMTP_HOST}
      SMTP_PORT: ${SMTP_PORT:-587}
      SMTP_USER: ${SMTP_USER}
      SMTP_PASSWORD: ${SMTP_PASSWORD}
      CORS_ALLOWED_ORIGINS: ${CORS_ORIGINS:-https://*.omnicommerce.io}
      RATE_LIMIT_RPS: "100"
      RATE_LIMIT_BURST: "200"
    ports:
      - "${API_PORT:-8080}:8080"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 15s
      timeout: 5s
      retries: 3
      start_period: 30s
    deploy:
      mode: replicated
      replicas: ${API_REPLICAS:-3}
      resources:
        limits:
          cpus: '2'
          memory: 2G
        reservations:
          cpus: '0.5'
          memory: 512M
      update_config:
        parallelism: 1
        delay: 10s
        failure_action: rollback
        order: start-first
      rollback_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s

  # Frontend: Web Storefront
  web:
    build:
      context: ../../frontend/web
      dockerfile: Dockerfile
      args:
        NEXT_PUBLIC_API_URL: https://api.${DOMAIN:-omnicommerce.io}/api/v1
        NEXT_PUBLIC_ENVIRONMENT: ${ENVIRONMENT:-production}
    image: registry.${DOMAIN:-omnicommerce.io}/omnicommerce-web:${APP_VERSION:-latest}
    container_name: omnicommerce-web
    restart: unless-stopped
    networks:
      - public
    environment:
      NODE_ENV: production
      NEXT_PUBLIC_API_URL: https://api.${DOMAIN:-omnicommerce.io}/api/v1
      NEXT_PUBLIC_CDN_URL: https://cdn.${DOMAIN:-omnicommerce.io}
      NEXT_PUBLIC_SENTRY_DSN: ${SENTRY_DSN}
    ports:
      - "${WEB_PORT:-3000}:3000"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000"]
      interval: 30s
      timeout: 10s
      retries: 3
    deploy:
      mode: replicated
      replicas: ${WEB_REPLICAS:-2}

  # Frontend: Admin Panel
  admin:
    build:
      context: ../../frontend/admin
      dockerfile: Dockerfile
      args:
        NEXT_PUBLIC_API_URL: https://api.${DOMAIN:-omnicommerce.io}/api/v1
    image: registry.${DOMAIN:-omnicommerce.io}/omnicommerce-admin:${APP_VERSION:-latest}
    container_name: omnicommerce-admin
    restart: unless-stopped
    networks:
      - public
    environment:
      NODE_ENV: production
      PORT: "3001"
    ports:
      - "${ADMIN_PORT:-3001}:3001"
    deploy:
      replicas: 1

  # Frontend: Vendor Dashboard
  vendor-dashboard:
    build:
      context: ../../frontend/vendor-dashboard
      dockerfile: Dockerfile
    image: registry.${DOMAIN:-omnicommerce.io}/omnicommerce-vendor:${APP_VERSION:-latest}
    container_name: omnicommerce-vendor-dashboard
    restart: unless-stopped
    networks:
      - public
    environment:
      NODE_ENV: production
      PORT: "3002"
    ports:
      - "${VENDOR_PORT:-3002}:3002"
    deploy:
      replicas: 1

  # ==================== NGINX REVERSE PROXY ====================

  nginx:
    image: nginx:1.26-alpine
    container_name: omnicommerce-nginx
    restart: unless-stopped
    networks:
      - public
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
      - nginx_logs:/var/log/nginx
    depends_on:
      - web
      - admin
      - vendor-dashboard
      - backend
    deploy:
      mode: replicated
      replicas: ${NGINX_REPLICAS:-2}
    healthcheck:
      test: ["CMD", "nginx", "-t"]
      interval: 30s
      timeout: 10s
      retries: 3

  # ==================== CERTBOT (Auto SSL) ====================

  certbot:
    image: certbot/certbot:latest
    container_name: omnicommerce-certbot
    restart: unless-stopped
    networks:
      - public
    volumes:
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew --webroot -w /var/www/certbot --quiet; sleep 12h & wait $${!}; done;'"
    profiles: [production]

  # ==================== TOOLS (Dev Only) ====================

  redisinsight:
    image: redis/redisinsight:latest
    container_name: omnicommerce-redisinsight
    restart: unless-stopped
    networks:
      - internal
      - monitoring
    ports:
      - "${REDISINSIGHT_PORT:-5540}:5540"
    volumes:
      - redisinsight_data:/data
    profiles: [dev]

  mailhog:
    image: mailhog/mailhog:latest
    container_name: omnicommerce-mailhog
    restart: unless-stopped
    networks:
      - internal
      - monitoring
    ports:
      - "${MAILHOG_SMTP_PORT:-1025}:1025"
      - "${MAILHOG_UI_PORT:-8025}:8025"
    profiles: [dev]

volumes:
  nginx_logs:
