#!/usr/bin/env bash
# Restart local development app services for Seg_Server.
# Infra services (PostgreSQL/Redis/MinIO) are checked and started if possible.

set -euo pipefail

PROJECT_DIR="${PROJECT_DIR:-/home/wkmgc/Desktop/Seg_Server}"
CONDA_ENV="${CONDA_ENV:-seg_server}"
CONDA_BIN="${CONDA_BIN:-${HOME}/miniconda3/bin/conda}"
BACKEND_PORT="${BACKEND_PORT:-8000}"
FRONTEND_PORT="${FRONTEND_PORT:-3000}"
LOG_DIR="${LOG_DIR:-/tmp}"
PID_DIR="${PID_DIR:-/tmp}"

FASTAPI_LOG="${LOG_DIR}/seg_server_fastapi.log"
CELERY_LOG="${LOG_DIR}/seg_server_celery.log"
FRONTEND_LOG="${LOG_DIR}/seg_server_frontend.log"
MINIO_LOG="${LOG_DIR}/seg_server_minio.log"
FASTAPI_PID="${PID_DIR}/seg_server_fastapi.pid"
CELERY_PID="${PID_DIR}/seg_server_celery.pid"
FRONTEND_PID="${PID_DIR}/seg_server_frontend.pid"
MINIO_PID="${PID_DIR}/seg_server_minio.pid"

echo "== Seg_Server development restart =="
echo "Project: ${PROJECT_DIR}"

start_system_service() {
  local service_name="$1"
  if command -v systemctl >/dev/null 2>&1; then
    sudo systemctl start "${service_name}"
  else
    echo "systemctl not found; please start ${service_name} manually." >&2
    return 1
  fi
}

ensure_conda() {
  if [[ -x "${CONDA_BIN}" ]]; then
    return
  fi
  if command -v conda >/dev/null 2>&1; then
    CONDA_BIN="$(command -v conda)"
    return
  fi
  echo "conda not found; set CONDA_BIN to the conda executable." >&2
  exit 1
}

stop_pidfile_group() {
  local pidfile="$1"
  if [[ ! -f "${pidfile}" ]]; then
    return
  fi
  local pid
  pid="$(cat "${pidfile}" 2>/dev/null || true)"
  rm -f "${pidfile}"
  if [[ -z "${pid}" ]]; then
    return
  fi
  if kill -0 "${pid}" >/dev/null 2>&1; then
    kill -- "-${pid}" >/dev/null 2>&1 || kill "${pid}" >/dev/null 2>&1 || true
  fi
}

start_detached() {
  local name="$1"
  local workdir="$2"
  local pidfile="$3"
  local logfile="$4"
  shift 4

  mkdir -p "$(dirname "${pidfile}")" "$(dirname "${logfile}")"
  : >"${logfile}"
  setsid bash -c 'cd "$1" || exit 1; shift; exec "$@"' bash "${workdir}" "$@" >"${logfile}" 2>&1 < /dev/null &
  local pid=$!
  echo "${pid}" >"${pidfile}"
  echo "  ${name} pid ${pid}"
}

wait_for_http() {
  local label="$1"
  local url="$2"
  local logfile="$3"
  local method="${4:-GET}"

  for _ in $(seq 1 30); do
    if [[ "${method}" == "HEAD" ]]; then
      curl -fsS -I "${url}" >/dev/null 2>&1 && echo "  ${label} ready" && return
    else
      curl -fsS "${url}" >/dev/null 2>&1 && echo "  ${label} ready" && return
    fi
    sleep 1
  done

  echo "${label} did not become ready: ${url}" >&2
  echo "Last log lines from ${logfile}:" >&2
  tail -n 80 "${logfile}" >&2 || true
  exit 1
}

wait_for_process() {
  local label="$1"
  local pidfile="$2"
  local logfile="$3"

  for _ in $(seq 1 8); do
    local pid
    pid="$(cat "${pidfile}" 2>/dev/null || true)"
    if [[ -n "${pid}" ]] && kill -0 "${pid}" >/dev/null 2>&1; then
      echo "  ${label} ready"
      return
    fi
    sleep 1
  done

  echo "${label} did not stay running." >&2
  echo "Last log lines from ${logfile}:" >&2
  tail -n 80 "${logfile}" >&2 || true
  exit 1
}

ensure_conda

echo "[1/6] Checking PostgreSQL..."
if ! pg_isready -q; then
  start_system_service postgresql
fi
pg_isready >/dev/null
echo "  PostgreSQL ready"

echo "[2/6] Checking Redis..."
if ! redis-cli ping >/dev/null 2>&1; then
  start_system_service redis-server
fi
redis-cli ping >/dev/null
echo "  Redis ready"

echo "[3/6] Checking MinIO..."
if ! curl -fsS http://localhost:9000/minio/health/live >/dev/null 2>&1; then
  stop_pidfile_group "${MINIO_PID}"
  start_detached "MinIO" "${PROJECT_DIR}" "${MINIO_PID}" "${MINIO_LOG}" minio server "${HOME}/minio_data" --console-address :9001
fi
wait_for_http "MinIO" "http://localhost:9000/minio/health/live" "${MINIO_LOG}"

echo "[4/6] Stopping app services..."
stop_pidfile_group "${FASTAPI_PID}"
stop_pidfile_group "${CELERY_PID}"
stop_pidfile_group "${FRONTEND_PID}"
pkill -f "uvicorn main:app --host .*--port ${BACKEND_PORT}" || true
pkill -f "uvicorn main:app" || true
pkill -f "conda run -n ${CONDA_ENV} uvicorn main:app" || true
pkill -f "celery -A celery_app:celery_app worker" || true
pkill -f "conda run -n ${CONDA_ENV} celery -A celery_app:celery_app worker" || true
pkill -f "${PROJECT_DIR}/node_modules/.bin/tsx server.ts" || true
pkill -f "npm run dev" || true
sleep 1

echo "[5/6] Starting backend and worker..."
start_detached "FastAPI" "${PROJECT_DIR}/backend" "${FASTAPI_PID}" "${FASTAPI_LOG}" \
  "${CONDA_BIN}" run -n "${CONDA_ENV}" uvicorn main:app --host 0.0.0.0 --port "${BACKEND_PORT}"
start_detached "Celery" "${PROJECT_DIR}/backend" "${CELERY_PID}" "${CELERY_LOG}" \
  "${CONDA_BIN}" run -n "${CONDA_ENV}" celery -A celery_app:celery_app worker --loglevel=info --pool=solo --concurrency=1

echo "[6/6] Starting frontend..."
start_detached "Frontend" "${PROJECT_DIR}" "${FRONTEND_PID}" "${FRONTEND_LOG}" npm run dev

wait_for_http "FastAPI" "http://127.0.0.1:${BACKEND_PORT}/health" "${FASTAPI_LOG}"
wait_for_process "Celery" "${CELERY_PID}" "${CELERY_LOG}"
wait_for_http "Frontend" "http://127.0.0.1:${FRONTEND_PORT}" "${FRONTEND_LOG}" HEAD

echo "== Restart complete =="
echo "Frontend: http://localhost:${FRONTEND_PORT}"
echo "Backend:  http://localhost:${BACKEND_PORT}/docs"
echo "PID files:"
echo "  FastAPI:  ${FASTAPI_PID}"
echo "  Celery:   ${CELERY_PID}"
echo "  Frontend: ${FRONTEND_PID}"
echo "Logs:"
echo "  FastAPI:  ${FASTAPI_LOG}"
echo "  Celery:   ${CELERY_LOG}"
echo "  Frontend: ${FRONTEND_LOG}"
echo "  MinIO:    ${MINIO_LOG}"
