# Monaco USA Portal - Production Docker Compose
# For deployment on Debian/Linux servers with Traefik reverse proxy
#
# Usage:
#   1. Copy .env.production.example to .env
#   2. Configure all environment variables
#   3. Run: docker compose -f docker-compose.prod.yml up -d
#
# Prerequisites:
#   - Docker and Docker Compose installed
#   - Domain DNS pointing to server IP
#   - Ports 80 and 443 open

services:
  # ============================================
  # Traefik Reverse Proxy (SSL/HTTPS)
  # ============================================
  traefik:
    image: traefik:v3.0
    container_name: monacousa-traefik
    restart: unless-stopped
    command:
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
      - "--entrypoints.web.http.redirections.entryPoint.scheme=https"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
      - "--certificatesresolvers.letsencrypt.acme.email=${ACME_EMAIL}"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      - "--log.level=INFO"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - traefik-certs:/letsencrypt
    networks:
      - monacousa-network
    labels:
      # Traefik dashboard (optional - remove in production if not needed)
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.rule=Host(`traefik.${DOMAIN}`)"
      - "traefik.http.routers.traefik.entrypoints=websecure"
      - "traefik.http.routers.traefik.tls.certresolver=letsencrypt"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.middlewares=traefik-auth"
      - "traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK_DASHBOARD_AUTH}"

  # ============================================
  # PostgreSQL Database
  # ============================================
  db:
    image: supabase/postgres:15.8.1.060
    container_name: monacousa-db
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
      JWT_SECRET: ${JWT_SECRET}
      JWT_EXP: ${JWT_EXPIRY}
    volumes:
      - db-data:/var/lib/postgresql/data
      - ./supabase/migrations:/docker-entrypoint-initdb.d
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - monacousa-network
    deploy:
      resources:
        limits:
          memory: 2G
        reservations:
          memory: 512M
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # ============================================
  # Supabase Studio (Dashboard) - Optional
  # ============================================
  studio:
    image: supabase/studio:20241202-71e5240
    container_name: monacousa-studio
    restart: unless-stopped
    environment:
      STUDIO_PG_META_URL: http://meta:8080
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      DEFAULT_ORGANIZATION_NAME: Monaco USA
      DEFAULT_PROJECT_NAME: Monaco USA Portal
      SUPABASE_URL: http://kong:8000
      SUPABASE_PUBLIC_URL: https://api.${DOMAIN}
      SUPABASE_ANON_KEY: ${ANON_KEY}
      SUPABASE_SERVICE_KEY: ${SERVICE_ROLE_KEY}
    depends_on:
      meta:
        condition: service_healthy
    networks:
      - monacousa-network
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.studio.rule=Host(`studio.${DOMAIN}`)"
      - "traefik.http.routers.studio.entrypoints=websecure"
      - "traefik.http.routers.studio.tls.certresolver=letsencrypt"
      - "traefik.http.services.studio.loadbalancer.server.port=3000"
      - "traefik.http.routers.studio.middlewares=studio-auth"
      - "traefik.http.middlewares.studio-auth.basicauth.users=${STUDIO_AUTH}"
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # ============================================
  # Kong API Gateway
  # ============================================
  kong:
    image: kong:2.8.1
    container_name: monacousa-kong
    restart: unless-stopped
    environment:
      KONG_DATABASE: "off"
      KONG_DECLARATIVE_CONFIG: /var/lib/kong/kong.yml
      KONG_DNS_ORDER: LAST,A,CNAME
      KONG_PLUGINS: request-transformer,cors,key-auth,acl,basic-auth
      KONG_NGINX_PROXY_PROXY_BUFFER_SIZE: 160k
      KONG_NGINX_PROXY_PROXY_BUFFERS: 64 160k
    volumes:
      - ./supabase/docker/kong.yml:/var/lib/kong/kong.yml:ro
    depends_on:
      auth:
        condition: service_healthy
    networks:
      - monacousa-network
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.kong.rule=Host(`api.${DOMAIN}`)"
      - "traefik.http.routers.kong.entrypoints=websecure"
      - "traefik.http.routers.kong.tls.certresolver=letsencrypt"
      - "traefik.http.services.kong.loadbalancer.server.port=8000"
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # ============================================
  # GoTrue (Auth)
  # ============================================
  auth:
    image: supabase/gotrue:v2.164.0
    container_name: monacousa-auth
    restart: unless-stopped
    environment:
      GOTRUE_API_HOST: 0.0.0.0
      GOTRUE_API_PORT: 9999
      API_EXTERNAL_URL: https://api.${DOMAIN}

      GOTRUE_DB_DRIVER: postgres
      GOTRUE_DB_DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?search_path=auth

      GOTRUE_SITE_URL: https://${DOMAIN}
      GOTRUE_URI_ALLOW_LIST: ${ADDITIONAL_REDIRECT_URLS}
      GOTRUE_DISABLE_SIGNUP: ${DISABLE_SIGNUP}

      GOTRUE_JWT_ADMIN_ROLES: service_role
      GOTRUE_JWT_AUD: authenticated
      GOTRUE_JWT_DEFAULT_GROUP_NAME: authenticated
      GOTRUE_JWT_EXP: ${JWT_EXPIRY}
      GOTRUE_JWT_SECRET: ${JWT_SECRET}

      GOTRUE_EXTERNAL_EMAIL_ENABLED: true
      GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED: false
      GOTRUE_MAILER_AUTOCONFIRM: ${ENABLE_EMAIL_AUTOCONFIRM}

      GOTRUE_SMTP_HOST: ${SMTP_HOST}
      GOTRUE_SMTP_PORT: ${SMTP_PORT}
      GOTRUE_SMTP_USER: ${SMTP_USER}
      GOTRUE_SMTP_PASS: ${SMTP_PASS}
      GOTRUE_SMTP_ADMIN_EMAIL: ${SMTP_ADMIN_EMAIL}
      GOTRUE_SMTP_SENDER_NAME: ${SMTP_SENDER_NAME}
      GOTRUE_MAILER_URLPATHS_INVITE: /auth/verify
      GOTRUE_MAILER_URLPATHS_CONFIRMATION: /auth/verify
      GOTRUE_MAILER_URLPATHS_RECOVERY: /auth/verify
      GOTRUE_MAILER_URLPATHS_EMAIL_CHANGE: /auth/verify

      GOTRUE_RATE_LIMIT_EMAIL_SENT: ${RATE_LIMIT_EMAIL_SENT}
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9999/health"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - monacousa-network
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # ============================================
  # PostgREST (REST API)
  # ============================================
  rest:
    image: postgrest/postgrest:v12.2.0
    container_name: monacousa-rest
    restart: unless-stopped
    environment:
      PGRST_DB_URI: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
      PGRST_DB_SCHEMAS: ${PGRST_DB_SCHEMAS}
      PGRST_DB_ANON_ROLE: anon
      PGRST_JWT_SECRET: ${JWT_SECRET}
      PGRST_DB_USE_LEGACY_GUCS: "false"
      PGRST_APP_SETTINGS_JWT_SECRET: ${JWT_SECRET}
      PGRST_APP_SETTINGS_JWT_EXP: ${JWT_EXPIRY}
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "exit 0"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s
    networks:
      - monacousa-network
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # ============================================
  # Realtime
  # ============================================
  realtime:
    image: supabase/realtime:v2.33.58
    container_name: monacousa-realtime
    restart: unless-stopped
    environment:
      PORT: 4000
      DB_HOST: db
      DB_PORT: 5432
      DB_USER: supabase_admin
      DB_PASSWORD: ${POSTGRES_PASSWORD}
      DB_NAME: ${POSTGRES_DB}
      DB_AFTER_CONNECT_QUERY: 'SET search_path TO _realtime'
      DB_ENC_KEY: supabaserealtime
      API_JWT_SECRET: ${JWT_SECRET}
      SECRET_KEY_BASE: ${SECRET_KEY_BASE}
      ERL_AFLAGS: -proto_dist inet_tcp
      DNS_NODES: "''"
      RLIMIT_NOFILE: "10000"
      APP_NAME: realtime
      SEED_SELF_HOST: true
    depends_on:
      db:
        condition: service_healthy
    networks:
      - monacousa-network
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # ============================================
  # Storage API
  # ============================================
  storage:
    image: supabase/storage-api:v1.11.13
    container_name: monacousa-storage
    restart: unless-stopped
    environment:
      ANON_KEY: ${ANON_KEY}
      SERVICE_KEY: ${SERVICE_ROLE_KEY}
      POSTGREST_URL: http://rest:3000
      PGRST_JWT_SECRET: ${JWT_SECRET}
      DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
      FILE_SIZE_LIMIT: 52428800
      STORAGE_BACKEND: file
      FILE_STORAGE_BACKEND_PATH: /var/lib/storage
      TENANT_ID: stub
      REGION: stub
      GLOBAL_S3_BUCKET: stub
      ENABLE_IMAGE_TRANSFORMATION: "true"
      IMGPROXY_URL: http://imgproxy:8080
    volumes:
      - storage-data:/var/lib/storage
    depends_on:
      db:
        condition: service_healthy
      rest:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5000/status"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - monacousa-network
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # ============================================
  # Image Proxy (for storage transformations)
  # ============================================
  imgproxy:
    image: darthsim/imgproxy:v3.8.0
    container_name: monacousa-imgproxy
    restart: unless-stopped
    environment:
      IMGPROXY_BIND: ":8080"
      IMGPROXY_LOCAL_FILESYSTEM_ROOT: /
      IMGPROXY_USE_ETAG: "true"
      IMGPROXY_ENABLE_WEBP_DETECTION: "true"
    volumes:
      - storage-data:/var/lib/storage
    healthcheck:
      test: ["CMD", "imgproxy", "health"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - monacousa-network
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # ============================================
  # Postgres Meta (for Studio)
  # ============================================
  meta:
    image: supabase/postgres-meta:v0.84.2
    container_name: monacousa-meta
    restart: unless-stopped
    environment:
      PG_META_PORT: 8080
      PG_META_DB_HOST: db
      PG_META_DB_PORT: 5432
      PG_META_DB_NAME: ${POSTGRES_DB}
      PG_META_DB_USER: supabase_admin
      PG_META_DB_PASSWORD: ${POSTGRES_PASSWORD}
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "exit 0"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s
    networks:
      - monacousa-network
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  # ============================================
  # Monaco USA Portal (SvelteKit App)
  # ============================================
  portal:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        PUBLIC_SUPABASE_URL: https://api.${DOMAIN}
        PUBLIC_SUPABASE_ANON_KEY: ${ANON_KEY}
        SUPABASE_SERVICE_ROLE_KEY: ${SERVICE_ROLE_KEY}
    container_name: monacousa-portal
    restart: unless-stopped
    environment:
      PUBLIC_SUPABASE_URL: https://api.${DOMAIN}
      PUBLIC_SUPABASE_ANON_KEY: ${ANON_KEY}
      SUPABASE_SERVICE_ROLE_KEY: ${SERVICE_ROLE_KEY}
      SUPABASE_INTERNAL_URL: http://kong:8000
      NODE_ENV: production
      ORIGIN: https://${DOMAIN}
      BODY_SIZE_LIMIT: ${BODY_SIZE_LIMIT}
    depends_on:
      kong:
        condition: service_started
      db:
        condition: service_healthy
    networks:
      - monacousa-network
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.portal.rule=Host(`${DOMAIN}`)"
      - "traefik.http.routers.portal.entrypoints=websecure"
      - "traefik.http.routers.portal.tls.certresolver=letsencrypt"
      - "traefik.http.services.portal.loadbalancer.server.port=3000"
    deploy:
      resources:
        limits:
          memory: 1G
        reservations:
          memory: 256M
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

# ============================================
# Networks
# ============================================
networks:
  monacousa-network:
    driver: bridge

# ============================================
# Volumes
# ============================================
volumes:
  db-data:
    driver: local
  storage-data:
    driver: local
  traefik-certs:
    driver: local
