#!/usr/bin/env bash
# Generate docker-compose.packages.yml: one named volume per workspace package
# in the frontend monorepo, so no host node_modules directory is ever visible
# inside the containers. Regenerated on every up/rebuild, never committed.
source "$(dirname "${BASH_SOURCE[0]}")/common.sh"

OUT="${RUN_DIR}/docker-compose.packages.yml"
FRONTEND_SERVICES="frontend-deps frontend-packages frontend-sync web admin landing mobile-deps mobile-packages mobile-client"

# Extra apps are frontend services too, so they need the same shadowing.
FRONTEND_SERVICES="${FRONTEND_SERVICES} $(extra_app_names | tr '\n' ' ')"

# Every directory that holds a package.json, one level under a workspace root.
package_dirs() {
  local root
  for root in ${WORKSPACE_ROOTS:-apps packages}; do
    [ -d "${FRONTEND_DIR}/${root}" ] || continue
    find "${FRONTEND_DIR}/${root}" -mindepth 2 -maxdepth 2 -name package.json \
      | sed "s|^${FRONTEND_DIR}/||; s|/package.json$||" \
      | sort
  done
}

# apps/mobile-client -> fe_nm_apps_mobile_client
volume_name() {
  echo "fe_nm_$(echo "$1" | tr '/-' '__')"
}

# A Node backend needs the same treatment as the frontend: its node_modules
# must never be the host's. Laravel keeps vendor/ in the bind mount, so there
# is nothing to shadow there.
#
# When the API lives in the same monorepo as the frontend, the backend reuses
# the frontend's volumes — one pnpm install, and the workspace symlinks between
# the API and the shared packages resolve on both sides.
backend_in_frontend_repo() {
  [ "${BACKEND_DIR%/}" = "${FRONTEND_DIR%/}" ]
}

backend_block() {
  [ "${BACKEND_STACK}" = "node" ] || return 0
  local service
  for service in backend queue scheduler; do
    echo "  ${service}:"
    echo "    volumes:"
    echo "      - pnpm_store:/pnpm-store"
    echo "      - fe_nm_root:/app/node_modules"
    if backend_in_frontend_repo; then
      if [ -n "${DIRS}" ]; then
        while read -r dir; do
          echo "      - $(volume_name "${dir}"):/app/${dir}/node_modules"
        done <<<"${DIRS}"
      fi
      # frontend-deps owns the single pnpm install for the whole workspace.
      echo "    depends_on:"
      echo "      frontend-deps:"
      echo "        condition: service_completed_successfully"
    elif [ -n "${BACKEND_SUBDIR:-}" ]; then
      echo "      - be_node_modules:/app/${BACKEND_SUBDIR%/}/node_modules"
    fi
  done
}

backend_volumes() {
  [ "${BACKEND_STACK}" = "node" ] || return 0
  if ! backend_in_frontend_repo && [ -n "${BACKEND_SUBDIR:-}" ]; then
    echo "  be_node_modules:"
  fi
}

# When the workspace has no mobile app, park Metro services behind a profile
# plain `docker compose up` never selects — no RUN_MOBILE flag required when
# an expo/react-native app is present.
mobile_gate_block() {
  mobile_enabled && return 0
  local service
  for service in mobile-deps mobile-packages mobile-client; do
    echo "  ${service}:"
    echo "    profiles: [\"__no_mobile\"]"
  done
}

DIRS="$(package_dirs)"

if [ -z "${DIRS}" ]; then
  {
    echo "# Generated by run/scripts/gen-packages.sh — no workspace packages found."
    if [ "${BACKEND_STACK}" = "node" ]; then
      echo "services:"
      backend_block
      mobile_gate_block
      echo "volumes:"
      backend_volumes
    else
      echo "services:"
      mobile_gate_block
      echo "volumes: {}"
    fi
  } >"${OUT}"
  echo "[run] no workspace packages found under ${FRONTEND_DIR}"
  exit 0
fi

{
  echo "# Generated by run/scripts/gen-packages.sh — do not edit."
  echo "services:"
  backend_block
  for service in ${FRONTEND_SERVICES}; do
    echo "  ${service}:"
    # The gate belongs in this block, not a second one: two mappings for the
    # same service in one file is a YAML duplicate key, which compose refuses
    # to parse at all.
    if ! mobile_enabled; then
      case "${service}" in
        mobile-deps|mobile-packages|mobile-client) echo "    profiles: [\"__no_mobile\"]" ;;
      esac
    fi
    echo "    volumes:"
    while read -r dir; do
      echo "      - $(volume_name "${dir}"):/app/${dir}/node_modules"
    done <<<"${DIRS}"
  done
  echo "volumes:"
  backend_volumes
  while read -r dir; do
    echo "  $(volume_name "${dir}"):"
  done <<<"${DIRS}"
} >"${OUT}"

echo "[run] wrote $(basename "${OUT}") ($(echo "${DIRS}" | wc -l | tr -d ' ') packages)"
