services:
  nginx:
    image: nginx:1.27-alpine
    container_name: taskco-app-nginx
    restart: unless-stopped
    ports:
      # Apache owns host :80/:443. Docker nginx on 8080 → container 80.
      - "8080:80"
    volumes:
      - ./.docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./.docker/nginx/app/prod.conf:/etc/nginx/conf.d/default.conf:ro
      - ./.docker/nginx/includes:/etc/nginx/includes:ro
      - ./app/public:/var/www/html/public:ro
    depends_on:
      app:
        condition: service_healthy
      nextjs:
        condition: service_started
    networks:
      - taskco_network
    healthcheck:
      test: ["CMD-SHELL", "wget -qO /dev/null http://127.0.0.1/health || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 15s

  app:
    build:
      context: .
      dockerfile: .docker/app/prod/Dockerfile
    image: taskco-app:latest
    container_name: taskco-app
    restart: unless-stopped
    env_file:
      - .env
    environment:
      AUTO_MIGRATE: "true"
      AUTO_FIX_PERMISSIONS: "true"
    volumes:
      - taskco-app-storage:/var/www/html/storage
      - taskco-app-bootstrap-cache:/var/www/html/bootstrap/cache
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - taskco_network
    healthcheck:
      test:
        ["CMD-SHELL", "wget -q --spider http://127.0.0.1:8000/health || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

  nextjs:
    build:
      context: ./web
      dockerfile: ../.docker/web/prod/Dockerfile
      # NEXT_PUBLIC_* are baked into the JS bundle at BUILD time.
      # Setting them as runtime env has NO effect.
      # NEXT_PUBLIC_API_URL is intentionally empty: api.ts falls back to
      # window.location.origin at runtime, so every tenant's site calls
      # its own backend without a per-tenant build.
      args:
        NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-}
        NEXT_PUBLIC_PREVIEW_URL: ${NEXT_PUBLIC_PREVIEW_URL:-https://taskco.tech}
        NEXT_PUBLIC_MAIN_DOMAIN: ${NEXT_PUBLIC_MAIN_DOMAIN:-https://taskco.tech}
    image: taskco-nextjs:latest
    container_name: taskco-nextjs
    restart: unless-stopped
    environment:
      NODE_ENV: production
      HOSTNAME: "0.0.0.0"
      PORT: "3000"
      NEXT_TELEMETRY_DISABLED: "1"
    networks:
      - taskco_network
    healthcheck:
      test: ["CMD-SHELL", "wget -qO /dev/null http://127.0.0.1:3000/ || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
    ports:
      - "3000:3000"
  postgres:
    image: postgres:16-alpine
    container_name: taskco-app-postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${DB_DATABASE} # e.g., taskco
      POSTGRES_USER: ${DB_USERNAME} # e.g., taskco_admin
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    env_file:
      - .env
    ports:
      - "5442:5432"
    volumes:
      - taskco-app-postgres-data:/var/lib/postgresql/data
    networks:
      - taskco_network
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "pg_isready -h localhost -U ${DB_USERNAME} -d ${DB_DATABASE}",
        ]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

  redis:
    image: redis:7-alpine
    container_name: taskco-app-redis
    restart: unless-stopped
    ports:
      - "6382:6379"
    volumes:
      - taskco-app-redis-data:/data
    networks:
      - taskco_network
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

  worker:
    # Reuses app image (same PHP + extensions + supervisor).
    # Eliminates duplicate 500s PHP extension build.
    image: taskco-app:latest
    container_name: taskco-app-worker
    restart: unless-stopped
    env_file:
      - .env
    environment:
      CONTAINER_ROLE: worker
    entrypoint: ["/bin/sh", "-c"]
    command:
      - |
        chown -R appuser:appgroup /var/log/supervisor /var/run/supervisor 2>/dev/null || true
        chown -R appuser:appgroup /var/www/html/storage /var/www/html/bootstrap/cache 2>/dev/null || true
        exec /usr/bin/supervisord -c /etc/supervisord.conf
    extra_hosts:
      - "host.docker.internal:host-gateway"
    volumes:
      - ./app:/var/www/html
      # Supervisor configs mounted from host (not baked in app image)
      - ./.docker/worker/supervisord.conf:/etc/supervisord.conf:ro
      - ./.docker/worker/worker.conf:/etc/supervisor.d/worker.conf:ro
      # Worker-optimized opcache (enable_cli=1 for long-running processes)
      - ./.docker/worker/opcache.ini:/usr/local/etc/php/conf.d/opcache.ini:ro
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - taskco_network
    healthcheck:
      test: ["CMD-SHELL", "supervisorctl -c /etc/supervisord.conf status 2>/dev/null | grep -q RUNNING || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s

  scheduler:
    image: taskco-app:latest
    container_name: taskco-app-scheduler
    restart: unless-stopped
    command: ["php", "artisan", "schedule:work"]
    env_file:
      - .env
    environment:
      CONTAINER_ROLE: scheduler
    extra_hosts:
      - "host.docker.internal:host-gateway"
    volumes:
      - ./app:/var/www/html
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - taskco_network
    healthcheck:
      test: ["CMD-SHELL", "php /var/www/html/artisan schedule:list || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s

  horizon:
    image: taskco-app:latest
    container_name: taskco-app-horizon
    restart: unless-stopped
    command: ["php", "artisan", "horizon"]
    env_file:
      - .env
    environment:
      CONTAINER_ROLE: worker
      HORIZON_ENABLED: "true"
    volumes:
      - ./app:/var/www/html
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - taskco_network
    healthcheck:
      test: ["CMD-SHELL", "pgrep -f 'artisan horizon' || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
    profiles:
      - horizon

  mailpit:
    image: axllent/mailpit:latest
    container_name: taskco_mailpit
    ports:
      - "1026:1025" # SMTP server
      - "8026:8025" # Web UI
    restart: unless-stopped
    networks:
      - taskco_network

networks:
  taskco_network:
    driver: bridge

volumes:
  taskco-app-postgres-data:
  taskco-app-redis-data:
  taskco-app-storage:
  taskco-app-bootstrap-cache:
