#!/usr/bin/env bash
#
# Собирает (опционально) и складывает bootJar всех Spring-сервисов в одну папку
# serviceAllBuild/ в корне проекта, рядом кладёт config-repo и хелпер запуска run.sh.
#
# Использование:
#   ./serviceAllBuild.sh            # только собрать jar-ы в одно место (сервисы уже собраны)
#   ./serviceAllBuild.sh --build    # сначала ./gradlew bootJar, потом собрать в одно место
#
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
OUT="$ROOT/serviceAllBuild"
SERVICES_DIR="$ROOT/services"

DO_BUILD=0
[[ "${1:-}" == "--build" ]] && DO_BUILD=1

if [[ $DO_BUILD -eq 1 ]]; then
  echo "==> Сборка bootJar всех сервисов (./gradlew bootJar)..."
  "$ROOT/gradlew" bootJar
fi

mkdir -p "$OUT"

echo "==> Сбор jar-ов в $OUT"
count=0
for dir in "$SERVICES_DIR"/*/; do
  name="$(basename "$dir")"
  libs="$dir/build/libs"
  [[ -d "$libs" ]] || { echo "  - $name: нет build/libs (не Spring-сервис или не собран), пропуск"; continue; }
  # bootJar = единственный *.jar без суффикса -plain.jar; берём самый свежий по имени
  jar="$(find "$libs" -maxdepth 1 -name '*.jar' ! -name '*-plain.jar' | sort | tail -n1)"
  [[ -n "$jar" ]] || { echo "  - $name: bootJar не найден, пропуск"; continue; }
  cp -f "$jar" "$OUT/$name.jar"
  echo "  + $name.jar  <-  $(basename "$jar")"
  count=$((count + 1))
done

echo "==> Копирую config-repo в $OUT/config-repo (самодостаточная папка)"
rm -rf "$OUT/config-repo"
cp -r "$ROOT/config-repo" "$OUT/config-repo"

echo "==> Генерирую $OUT/run.sh"
cat > "$OUT/run.sh" <<'RUNEOF'
#!/usr/bin/env bash
#
# Запуск одного сервиса из собранной папки через java -jar.
#
#   ./run.sh                              # список доступных сервисов
#   ./run.sh spring-cloud-config-server   # ПЕРВЫМ всегда поднимаем config server
#   ./run.sh pcp-tgu-service              # затем нужные сервисы (в отдельных терминалах)
#
# Память не ограничена. Задать лимит при необходимости:
#   JAVA_OPTS="-Xmx384m" ./run.sh pcp-tgu-service
#
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_REPO="$HERE/config-repo"

JAVA_OPTS="${JAVA_OPTS:-}"

name="${1:-}"
if [[ -z "$name" ]]; then
  echo "Использование: ./run.sh <имя-сервиса>"
  echo
  echo "Сначала запусти config server:  ./run.sh spring-cloud-config-server"
  echo
  echo "Доступные сервисы:"
  for j in "$HERE"/*.jar; do basename "$j" .jar; done | sed 's/^/  /'
  exit 1
fi

jar="$HERE/$name.jar"
[[ -f "$jar" ]] || { echo "Нет файла: $jar"; exit 1; }

if [[ "$name" == "spring-cloud-config-server" ]]; then
  # config server в профиле local работает в native-режиме и читает yaml отсюда
  export SPRING_PROFILES_ACTIVE="${SPRING_PROFILES_ACTIVE:-local}"
  export CONFIG_NATIVE_SEARCH_LOCATIONS="${CONFIG_NATIVE_SEARCH_LOCATIONS:-optional:file:$CONFIG_REPO}"
  echo "==> config-repo: $CONFIG_REPO"
fi

echo "==> java $JAVA_OPTS -jar $name.jar"
exec java $JAVA_OPTS -jar "$jar"
RUNEOF
chmod +x "$OUT/run.sh"

echo "==> Генерирую $OUT/up.sh"
cat > "$OUT/up.sh" <<'UPEOF'
#!/usr/bin/env bash
#
# Поднять сразу несколько сервисов в фоне (config server — всегда первым).
#
#   ./up.sh                                  # запустить ВСЕ сервисы
#   ./up.sh pcp-tgu-service slots-service    # config server + перечисленные
#
# Имя сервиса = имя jar-файла без .jar. Логи: logs/<name>.log, pid: logs/<name>.pid.
# Погасить всё: ./down.sh
#
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_REPO="$HERE/config-repo"
LOGS="$HERE/logs"
mkdir -p "$LOGS"

JAVA_OPTS="${JAVA_OPTS:-}"
CFG="spring-cloud-config-server"

running() { local p="$LOGS/$1.pid"; [[ -f "$p" ]] && kill -0 "$(cat "$p")" 2>/dev/null; }

start_one() {
  local name="$1" jar="$HERE/$1.jar"
  [[ -f "$jar" ]] || { echo "  ! нет $name.jar, пропуск"; return; }
  if running "$name"; then echo "  = $name уже запущен (pid $(cat "$LOGS/$name.pid"))"; return; fi
  if [[ "$name" == "$CFG" ]]; then
    SPRING_PROFILES_ACTIVE="${SPRING_PROFILES_ACTIVE:-local}" \
    CONFIG_NATIVE_SEARCH_LOCATIONS="${CONFIG_NATIVE_SEARCH_LOCATIONS:-optional:file:$CONFIG_REPO}" \
      nohup java $JAVA_OPTS -jar "$jar" > "$LOGS/$name.log" 2>&1 &
  else
    nohup java $JAVA_OPTS -jar "$jar" > "$LOGS/$name.log" 2>&1 &
  fi
  echo $! > "$LOGS/$name.pid"
  echo "  + $name (pid $!) -> logs/$name.log"
}

wait_config_server() {
  printf "==> жду config server на :8888"
  for _ in $(seq 1 60); do
    if curl -sf http://localhost:8888/actuator/health >/dev/null 2>&1; then echo " — UP"; return 0; fi
    printf "."; sleep 2
  done
  echo " — не дождался; смотри logs/$CFG.log"; exit 1
}

targets=("$@")
if [[ ${#targets[@]} -eq 0 ]]; then
  for j in "$HERE"/*.jar; do targets+=("$(basename "$j" .jar)"); done
fi

echo "==> config server"
start_one "$CFG"
running "$CFG" && wait_config_server

echo "==> остальные сервисы"
for name in "${targets[@]}"; do
  [[ "$name" == "$CFG" ]] && continue
  start_one "$name"
done

echo "Готово. Логи: tail -f logs/<name>.log   Стоп: ./down.sh"
UPEOF
chmod +x "$OUT/up.sh"

echo "==> Генерирую $OUT/down.sh"
cat > "$OUT/down.sh" <<'DOWNEOF'
#!/usr/bin/env bash
#
# Погасить сервисы, запущенные через up.sh.
#   ./down.sh                       # погасить все
#   ./down.sh pcp-tgu-service ...   # погасить только перечисленные
#
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOGS="$HERE/logs"

names=("$@")
if [[ ${#names[@]} -eq 0 ]]; then
  shopt -s nullglob
  for p in "$LOGS"/*.pid; do names+=("$(basename "$p" .pid)"); done
fi

for name in "${names[@]}"; do
  p="$LOGS/$name.pid"
  [[ -f "$p" ]] || { echo "  - $name: pid-файла нет"; continue; }
  pid="$(cat "$p")"
  if kill -0 "$pid" 2>/dev/null; then kill "$pid"; echo "  x $name (pid $pid) остановлен"; else echo "  - $name (pid $pid) уже не жив"; fi
  rm -f "$p"
done
DOWNEOF
chmod +x "$OUT/down.sh"

echo "==> Генерирую $OUT/README.md"
cat > "$OUT/README.md" <<'MDEOF'
# serviceAllBuild — локальный запуск сервисов через `java -jar`

Папку формирует скрипт `../serviceAllBuild.sh`. Здесь лежат bootJar всех
Spring-сервисов, копия `config-repo` и хелпер `run.sh`.

## Куда класть config-repo

`spring-cloud-config-server` в профиле `local` работает в **native**-режиме и
читает yaml-файлы из локальной папки (а не из git). Папка `config-repo`
**уже скопирована сюда** скриптом сборки, и `run.sh` сам передаёт в config server
абсолютный путь к ней через `CONFIG_NATIVE_SEARCH_LOCATIONS`.

То есть ничего вручную раскладывать не нужно — достаточно запускать config server
через `./run.sh spring-cloud-config-server`. Если правишь конфиги — правь
`serviceAllBuild/config-repo/*.yaml` (или пересобери скриптом, чтобы подтянуть
изменения из корневого `config-repo`).

## Перед запуском: инфраструктура

Сервисам нужны (см. `config-repo/application-local.yaml`):
- PostgreSQL на `localhost:5432`
- Kafka на `localhost:29092`

Подними их (например, через docker-compose проекта) и создай БД скриптами из корня
(`create-service-dbs.sh` / `create_pcp_databases.sh`).

## Порядок запуска

Config server слушает порт **8888** — остальные сервисы ходят за конфигом именно
туда, поэтому он всегда первый. Имя сервиса = имя jar-файла без `.jar`.

### Несколько сервисов сразу (в фоне)

```bash
./up.sh                                # ВСЕ сервисы
./up.sh pcp-tgu-service slots-service  # config server + перечисленные
```

`up.sh` сам поднимает config server первым, ждёт его готовности на :8888, затем
запускает остальные в фоне. Логи — в `logs/<name>.log`, pid — в `logs/<name>.pid`.

```bash
tail -f logs/pcp-tgu-service.log   # смотреть лог
./down.sh                          # погасить все
./down.sh slots-service            # погасить один
```

### По одному (на переднем плане, каждый в своём терминале)

```bash
# терминал 1
./run.sh spring-cloud-config-server

# терминал 2 (после того как config server поднялся)
./run.sh pcp-tgu-service
```

Порты сервисов заданы в `config-repo/application-local.yaml` (`pcp.ports.*`):
tgu=7011, slots=7006, ui=7008, gateway=7080, request=7005, mission=7010 и т.д.

## Память

Лимит heap не задан — JVM сама возьмёт до 25% физической RAM на каждый процесс.
Запускай только то, что нужно прямо сейчас. При нехватке памяти можно ограничить
конкретный сервис:

```bash
JAVA_OPTS="-Xmx384m" ./run.sh pcp-mission-planing-service
```
MDEOF

echo
echo "Готово: $count сервисов в $OUT"
echo "Запуск:  cd serviceAllBuild && ./run.sh spring-cloud-config-server"
