services:
  fiscal-engine-v2:
    restart: unless-stopped
    build:
      context: .
      dockerfile: apps/fiscal-engine-v2/Dockerfile
    environment:
      FISCAL_ENGINE_V2_APP_ENVIRONMENT: ${APP_ENVIRONMENT:-development}
      FISCAL_ENGINE_V2_INTERNAL_TOKEN: ${LLM_PROXY_INTERNAL_TOKEN:?LLM_PROXY_INTERNAL_TOKEN is required}
      FISCAL_ENGINE_V2_ALLOWED_TENANT_SLUGS: ${FISCAL_ENGINE_V2_ALLOWED_TENANT_SLUGS:-test}
      FISCAL_ENGINE_V2_DATABASE_PATH: /data/fiscal-engine-v2.sqlite3
      FISCAL_ENGINE_V2_REGISTRY_DATABASE_PATH: /data/platform_registry.sqlite3
      FISCAL_ENGINE_V2_LLM_BASE_URL: ${LLM_BASE_URL:-https://api.groq.com/openai/v1}
      FISCAL_ENGINE_V2_LLM_API_KEY: ${LLM_API_KEY:-}
      FISCAL_ENGINE_V2_LLM_MODEL: ${FISCAL_ENGINE_V2_LLM_MODEL:-openai/gpt-oss-120b}
      FISCAL_ENGINE_V2_LLM_FALLBACK_MODELS: ${FISCAL_ENGINE_V2_LLM_FALLBACK_MODELS:-openai/gpt-oss-20b,qwen/qwen3-32b}
      FISCAL_ENGINE_V2_LLM_ENABLED: ${FISCAL_ENGINE_V2_LLM_ENABLED:-true}
      FISCAL_ENGINE_V2_GOOGLE_DOCUMENT_AI_PROJECT_ID: ${GOOGLE_DOCUMENT_AI_PROJECT_ID:-}
      FISCAL_ENGINE_V2_GOOGLE_DOCUMENT_AI_LOCATION: ${GOOGLE_DOCUMENT_AI_LOCATION:-eu}
      FISCAL_ENGINE_V2_GOOGLE_DOCUMENT_AI_OCR_PROCESSOR_ID: ${GOOGLE_DOCUMENT_AI_OCR_PROCESSOR_ID:-}
      FISCAL_ENGINE_V2_GOOGLE_DOCUMENT_AI_SERVICE_ACCOUNT_FILE: /secrets/document-ai.json
    expose:
      - "8000"
    healthcheck:
      test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=3)"]
      interval: 15s
      timeout: 5s
      retries: 5
    volumes:
      - backend_hub_state_data:/data
      - ./secrets:/secrets:ro
    networks:
      - platform

  portal:
    restart: unless-stopped
    build:
      context: .
      dockerfile: apps/portal/Dockerfile
      args:
        VITE_API_HUB_BASE_URL: ${BACKEND_HUB_PUBLIC_URL:-http://localhost:8101}
        VITE_LLM_BASE_URL: ${LLM_BASE_URL:-https://api.groq.com/openai/v1}
        VITE_PRENOTAZIONI_MODULE_URL: ${PRENOTAZIONI_FRONTEND_PUBLIC_URL:-http://localhost:3100}
        VITE_MENU_MODULE_URL: ${MENU_LEGACY_PUBLIC_URL:-http://localhost:3200}
        VITE_ORDINI_MODULE_URL: ${ORDINI_FRONTEND_PUBLIC_URL:-http://localhost:3300}
        VITE_ENABLE_SESSION_QUERY_TOKENS: ${ENABLE_SESSION_QUERY_TOKENS:-false}
    depends_on:
      - backend-hub
      - prenotazioni-frontend
      - menu-legacy
      - ordini-frontend
    ports:
      - "${PORTAL_PORT:-3000}:80"
    networks:
      - platform

  backend-hub:
    restart: unless-stopped
    build:
      context: .
      dockerfile: apps/backend-hub/Dockerfile
    depends_on:
      fiscal-engine-v2:
        condition: service_healthy
    environment:
      APP_ENVIRONMENT: ${APP_ENVIRONMENT:-development}
      BACKEND_HUB_CORS_ORIGINS: ${BACKEND_HUB_CORS_ORIGINS:-http://localhost:3000,http://localhost:3100,http://localhost:3200,http://localhost:3300}
      BACKEND_HUB_PUBLIC_URL: ${BACKEND_HUB_PUBLIC_URL:-http://localhost:8101}
      PORTAL_PUBLIC_URL: ${PORTAL_PUBLIC_URL:-http://localhost:3000}
      PRENOTAZIONI_FRONTEND_PUBLIC_URL: ${PRENOTAZIONI_FRONTEND_PUBLIC_URL:-http://localhost:3100}
      PRENOTAZIONI_BACKEND_PUBLIC_URL: ${PRENOTAZIONI_BACKEND_PUBLIC_URL:-http://localhost:8100}
      MENU_LEGACY_PUBLIC_URL: ${MENU_LEGACY_PUBLIC_URL:-http://localhost:3200}
      ORDINI_FRONTEND_PUBLIC_URL: ${ORDINI_FRONTEND_PUBLIC_URL:-http://localhost:3300}
      ORDINI_BACKEND_PUBLIC_URL: ${ORDINI_BACKEND_PUBLIC_URL:-http://localhost:8200}
      LLM_BASE_URL: ${LLM_BASE_URL:-https://api.groq.com/openai/v1}
      LLM_API_KEY: ${LLM_API_KEY:-}
      LLM_PROXY_INTERNAL_TOKEN: ${LLM_PROXY_INTERNAL_TOKEN:?LLM_PROXY_INTERNAL_TOKEN is required}
      LLM_REQUEST_TIMEOUT_SECONDS: ${LLM_REQUEST_TIMEOUT_SECONDS:-30}
      ASSISTANT_DISPLAY_NAME: ${ASSISTANT_DISPLAY_NAME:-Assistente Locale}
      ASSISTANT_MODEL: ${ASSISTANT_MODEL:-openai/gpt-oss-120b}
      ASSISTANT_PLANNER_MODEL: ${ASSISTANT_PLANNER_MODEL:-openai/gpt-oss-120b}
      ASSISTANT_SYNTHESIS_MODEL: ${ASSISTANT_SYNTHESIS_MODEL:-openai/gpt-oss-120b}
      ASSISTANT_FALLBACK_MODEL: ${ASSISTANT_FALLBACK_MODEL:-openai/gpt-oss-20b}
      ASSISTANT_MAX_TOKENS: ${ASSISTANT_MAX_TOKENS:-8000}
      ASSISTANT_REASONING_EFFORT: ${ASSISTANT_REASONING_EFFORT:-low}
      ASSISTANT_INCLUDE_REASONING: ${ASSISTANT_INCLUDE_REASONING:-false}
      ASSISTANT_TEMPERATURE: ${ASSISTANT_TEMPERATURE:-0.2}
      ASSISTANT_SYSTEM_PROMPT: ${ASSISTANT_SYSTEM_PROMPT:-Sei l'assistente operativo interno del locale. Rispondi sempre in italiano, con tono sobrio, pratico e orientato all'azione.}
      ASSISTANT_OPERATIONAL_CONTEXT: ${ASSISTANT_OPERATIONAL_CONTEXT:-Il backend-hub centralizzera' progressivamente dati sensibili, policy operative e contesto aziendale.}
      PUSH_VAPID_PRIVATE_KEY_FILE: ${PUSH_VAPID_PRIVATE_KEY_FILE:-/data/push-vapid-private.pem}
      PUSH_VAPID_SUBJECT: ${PUSH_VAPID_SUBJECT:-mailto:admin@powerup.cool}
      GOOGLE_WORKSPACE_CLIENT_ID: ${GOOGLE_WORKSPACE_CLIENT_ID:-}
      GOOGLE_WORKSPACE_CLIENT_SECRET: ${GOOGLE_WORKSPACE_CLIENT_SECRET:-}
      GOOGLE_WORKSPACE_REDIRECT_PATH: ${GOOGLE_WORKSPACE_REDIRECT_PATH:-/google-workspace/oauth/callback}
      GOOGLE_WORKSPACE_SCOPES: ${GOOGLE_WORKSPACE_SCOPES:-openid,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/documents,https://www.googleapis.com/auth/spreadsheets,https://www.googleapis.com/auth/drive}
      GOOGLE_WORKSPACE_STATE_FILE: ${GOOGLE_WORKSPACE_STATE_FILE:-/data/google_workspace_state.json}
      GOOGLE_WORKSPACE_REQUEST_TIMEOUT_SECONDS: ${GOOGLE_WORKSPACE_REQUEST_TIMEOUT_SECONDS:-20}
      GOOGLE_WORKSPACE_SHEET_PREVIEW_MAX_ROWS: ${GOOGLE_WORKSPACE_SHEET_PREVIEW_MAX_ROWS:-20}
      FISCAL_DOCUMENT_INBOX_POLL_SECONDS: ${FISCAL_DOCUMENT_INBOX_POLL_SECONDS:-900}
      FISCAL_ENGINE_V2_URL: ${FISCAL_ENGINE_V2_URL:-http://fiscal-engine-v2:8000}
      FISCAL_ENGINE_V2_INTERNAL_TOKEN: ${LLM_PROXY_INTERNAL_TOKEN:?LLM_PROXY_INTERNAL_TOKEN is required}
      FISCAL_ENGINE_V2_TENANT_SLUGS: ${FISCAL_ENGINE_V2_TENANT_SLUGS:-test}
      FISCAL_ENGINE_V2_REQUEST_TIMEOUT_SECONDS: ${FISCAL_ENGINE_V2_REQUEST_TIMEOUT_SECONDS:-120}
      GOOGLE_DOCUMENT_AI_PROJECT_ID: ${GOOGLE_DOCUMENT_AI_PROJECT_ID:-}
      GOOGLE_DOCUMENT_AI_LOCATION: ${GOOGLE_DOCUMENT_AI_LOCATION:-eu}
      GOOGLE_DOCUMENT_AI_OCR_PROCESSOR_ID: ${GOOGLE_DOCUMENT_AI_OCR_PROCESSOR_ID:-}
      GOOGLE_DOCUMENT_AI_INVOICE_PROCESSOR_ID: ${GOOGLE_DOCUMENT_AI_INVOICE_PROCESSOR_ID:-}
      GOOGLE_DOCUMENT_AI_SERVICE_ACCOUNT_FILE: ${GOOGLE_DOCUMENT_AI_SERVICE_ACCOUNT_FILE:-/secrets/document-ai.json}
      GOOGLE_DOCUMENT_AI_REQUEST_TIMEOUT_SECONDS: ${GOOGLE_DOCUMENT_AI_REQUEST_TIMEOUT_SECONDS:-30}
    ports:
      - "${BACKEND_HUB_PORT:-8101}:8000"
    volumes:
      - backend_hub_state_data:/data
      - ./secrets:/secrets:ro
    networks:
      - platform

  prenotazioni-db:
    restart: unless-stopped
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: ${PRENOTAZIONI_POSTGRES_DB:-restaurant_booking}
      POSTGRES_USER: ${PRENOTAZIONI_POSTGRES_USER:-postgres}
      POSTGRES_PASSWORD: ${PRENOTAZIONI_POSTGRES_PASSWORD:-postgres}
    ports:
      - "${PRENOTAZIONI_DB_PORT:-55432}:5432"
    volumes:
      - prenotazioni_postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${PRENOTAZIONI_POSTGRES_USER:-postgres} -d ${PRENOTAZIONI_POSTGRES_DB:-restaurant_booking}"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - platform

  prenotazioni-backend:
    restart: unless-stopped
    build:
      context: .
      dockerfile: apps/prenotazioni-legacy/backend.Dockerfile
    depends_on:
      prenotazioni-db:
        condition: service_healthy
    environment:
      APP_ENVIRONMENT: ${APP_ENVIRONMENT:-development}
      DATABASE_URL: ${PRENOTAZIONI_DATABASE_URL:-postgresql+psycopg2://postgres:postgres@prenotazioni-db:5432/restaurant_booking}
      BACKEND_CORS_ORIGINS: ${PRENOTAZIONI_BACKEND_CORS_ORIGINS:-http://localhost:3100,http://localhost:3000}
      PUBLIC_BASE_URL: ${PRENOTAZIONI_BACKEND_PUBLIC_URL:-http://localhost:8100}
      ASSISTANT_API_BASE_URL: ${ASSISTANT_API_BASE_URL:-http://backend-hub:8000}
      LLM_PROXY_INTERNAL_TOKEN: ${LLM_PROXY_INTERNAL_TOKEN:?LLM_PROXY_INTERNAL_TOKEN is required}
      ASSISTANT_TIMEOUT_SECONDS: ${ASSISTANT_TIMEOUT_SECONDS:-30}
      ASSISTANT_HISTORY_LIMIT: ${ASSISTANT_HISTORY_LIMIT:-12}
      ASSISTANT_REPLY_MAX_CHARS: ${ASSISTANT_REPLY_MAX_CHARS:-1500}
      WHATSAPP_ACCESS_TOKEN: ${WHATSAPP_ACCESS_TOKEN:-}
      WHATSAPP_PHONE_NUMBER_ID: ${WHATSAPP_PHONE_NUMBER_ID:-}
      WHATSAPP_VERIFY_TOKEN: ${WHATSAPP_VERIFY_TOKEN:-}
      WHATSAPP_APP_SECRET: ${WHATSAPP_APP_SECRET:-}
      WHATSAPP_GRAPH_API_VERSION: ${WHATSAPP_GRAPH_API_VERSION:-v21.0}
    ports:
      - "${PRENOTAZIONI_BACKEND_PORT:-8100}:8000"
    networks:
      - platform

  prenotazioni-frontend:
    restart: unless-stopped
    build:
      context: .
      dockerfile: apps/prenotazioni-legacy/frontend.Dockerfile
      args:
        NEXT_PUBLIC_API_BASE_URL: ${PRENOTAZIONI_BACKEND_PUBLIC_URL:-http://localhost:8100}
        NEXT_PUBLIC_BASE_PATH: ${PRENOTAZIONI_FRONTEND_BASE_PATH:-}
        NEXT_PUBLIC_ENABLE_SESSION_QUERY_TOKENS: ${ENABLE_SESSION_QUERY_TOKENS:-false}
    depends_on:
      - prenotazioni-backend
    ports:
      - "${PRENOTAZIONI_FRONTEND_PORT:-3100}:3000"
    networks:
      - platform

  menu-legacy:
    restart: unless-stopped
    build:
      context: .
      dockerfile: apps/menu-legacy/Dockerfile
    ports:
      - "${MENU_LEGACY_PORT:-3200}:80"
    networks:
      - platform

  ordini-db:
    restart: unless-stopped
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: ${ORDINI_POSTGRES_DB:-orders_management}
      POSTGRES_USER: ${ORDINI_POSTGRES_USER:-postgres}
      POSTGRES_PASSWORD: ${ORDINI_POSTGRES_PASSWORD:-postgres}
    ports:
      - "${ORDINI_DB_PORT:-55433}:5432"
    volumes:
      - ordini_postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${ORDINI_POSTGRES_USER:-postgres} -d ${ORDINI_POSTGRES_DB:-orders_management}"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - platform

  ordini-backend:
    restart: unless-stopped
    build:
      context: .
      dockerfile: apps/ordini/backend/Dockerfile
    depends_on:
      ordini-db:
        condition: service_healthy
    environment:
      APP_ENVIRONMENT: ${APP_ENVIRONMENT:-development}
      DATABASE_URL: ${ORDINI_DATABASE_URL:-postgresql+psycopg2://postgres:postgres@ordini-db:5432/orders_management}
      BACKEND_CORS_ORIGINS: ${ORDINI_BACKEND_CORS_ORIGINS:-http://localhost:3300,http://localhost:3000}
      PUBLIC_BASE_URL: ${ORDINI_BACKEND_PUBLIC_URL:-http://localhost:8200}
      FRONTEND_PUBLIC_URL: ${ORDINI_FRONTEND_PUBLIC_URL:-http://localhost:3300}
      ADMIN_PASSWORD: ${ORDINI_ADMIN_PASSWORD:?ORDINI_ADMIN_PASSWORD is required}
      API_TOKEN: ${ORDINI_API_TOKEN:?ORDINI_API_TOKEN is required}
      DEFAULT_STAFF: ${ORDINI_DEFAULT_STAFF:-club}
      TENANCY_REGISTRY_DATABASE: ${TENANCY_REGISTRY_DATABASE:-/data/platform_registry.sqlite3}
      TENANCY_SESSION_DURATION_HOURS: ${TENANCY_SESSION_DURATION_HOURS:-168}
      PUSH_VAPID_PRIVATE_KEY_FILE: ${PUSH_VAPID_PRIVATE_KEY_FILE:-/data/push-vapid-private.pem}
      PUSH_VAPID_SUBJECT: ${PUSH_VAPID_SUBJECT:-mailto:admin@powerup.cool}
      SAFETY_STOCK_NOTIFICATION_POLL_SECONDS: ${SAFETY_STOCK_NOTIFICATION_POLL_SECONDS:-900}
    ports:
      - "${ORDINI_BACKEND_PORT:-8200}:8000"
    volumes:
      - backend_hub_state_data:/data
    networks:
      - platform

  ordini-frontend:
    restart: unless-stopped
    build:
      context: .
      dockerfile: apps/ordini/frontend/Dockerfile
    depends_on:
      - ordini-backend
    ports:
      - "${ORDINI_FRONTEND_PORT:-3300}:80"
    networks:
      - platform

networks:
  platform:
    name: hospitality-platform-network

volumes:
  prenotazioni_postgres_data:
  ordini_postgres_data:
  backend_hub_state_data:
