#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT_DIR"

API_HOST="${DEPATLAS_HOST:-127.0.0.1}"
API_PORT="${DEPATLAS_PORT:-8099}"
STORE_ROOT="${DEPATLAS_STORE:-.depatlas-store}"
FRONTEND_HOST="${DEPATLAS_FRONTEND_HOST:-127.0.0.1}"
FRONTEND_PORT="${DEPATLAS_FRONTEND_PORT:-5174}"
START_FRONTEND=1
START_BACKEND=1

BACKEND_ARGS=()

print_help() {
  cat <<'EOF'
DependencyAtlas dev launcher

Usage:
  ./bin/depatlas-server [options] [-- backend-args...]

Options:
  --frontend-only           Start only the Vite dev server.
  --backend-only            Start only the Julia API server.
  --frontend-host HOST      Override frontend host (default: 127.0.0.1).
  --frontend-port PORT      Override frontend port (default: 5174).
  --host HOST               Override backend host (default: 127.0.0.1).
  --port PORT               Override backend port (default: 8099).
  --store PATH              Override backend store root (default: .depatlas-store).
  -h, --help                Show this help.

Any remaining args after `--` are passed directly to the Julia backend.

Environment overrides:
  DEPATLAS_HOST
  DEPATLAS_PORT
  DEPATLAS_STORE
  DEPATLAS_FRONTEND_HOST
  DEPATLAS_FRONTEND_PORT
EOF
}

while (($# > 0)); do
  case "$1" in
    --frontend-only)
      START_BACKEND=0
      shift
      ;;
    --backend-only)
      START_FRONTEND=0
      shift
      ;;
    --frontend-host)
      FRONTEND_HOST="$2"
      shift 2
      ;;
    --frontend-port)
      FRONTEND_PORT="$2"
      shift 2
      ;;
    --host)
      API_HOST="$2"
      shift 2
      ;;
    --port)
      API_PORT="$2"
      shift 2
      ;;
    --store)
      STORE_ROOT="$2"
      shift 2
      ;;
    -h|--help)
      print_help
      exit 0
      ;;
    --)
      shift
      BACKEND_ARGS+=("$@")
      break
      ;;
    *)
      BACKEND_ARGS+=("$1")
      shift
      ;;
  esac
done

if [[ "$START_FRONTEND" -eq 0 && "$START_BACKEND" -eq 0 ]]; then
  echo "Nothing to start: both frontend and backend are disabled." >&2
  exit 1
fi

ensure_npm() {
  if command -v npm >/dev/null 2>&1; then
    return 0
  fi
  if [[ -s "$HOME/.nvm/nvm.sh" ]]; then
    # shellcheck disable=SC1090
    source "$HOME/.nvm/nvm.sh"
  fi
  command -v npm >/dev/null 2>&1
}

cleanup() {
  local exit_code=$?
  trap - EXIT INT TERM
  for pid in "${PIDS[@]:-}"; do
    if [[ -n "${pid:-}" ]] && kill -0 "$pid" >/dev/null 2>&1; then
      kill "$pid" >/dev/null 2>&1 || true
    fi
  done
  wait >/dev/null 2>&1 || true
  exit "$exit_code"
}

PIDS=()
trap cleanup EXIT INT TERM

if [[ "$START_FRONTEND" -eq 1 ]]; then
  ensure_npm || {
    echo "npm is not available. Install Node.js/npm or configure nvm before starting the frontend." >&2
    exit 1
  }
  echo "Starting frontend dev server on http://${FRONTEND_HOST}:${FRONTEND_PORT}"
  npm run dev -- --host "$FRONTEND_HOST" --port "$FRONTEND_PORT" &
  PIDS+=("$!")
fi

if [[ "$START_BACKEND" -eq 1 ]]; then
  echo "Starting backend API server on http://${API_HOST}:${API_PORT}"
  julia --project=. --startup-file=no -e '
    using DependencyAtlas

    function parse_args(args)
        host = get(ENV, "DEPATLAS_HOST", "127.0.0.1")
        port = try
            parse(Int, get(ENV, "DEPATLAS_PORT", "8099"))
        catch
            8099
        end
        store_root = get(ENV, "DEPATLAS_STORE", ".depatlas-store")
        static_root = String(strip(get(ENV, "DEPATLAS_STATIC_ROOT", joinpath(pwd(), "dist"))))
        static = lowercase(strip(get(ENV, "DEPATLAS_STATIC", ""))) in ("1", "true", "yes", "on")

        i = 1
        while i <= length(args)
            if args[i] == "--host" && i < length(args)
                host = args[i+1]
                i += 2
            elseif args[i] == "--port" && i < length(args)
                port = parse(Int, args[i+1])
                i += 2
            elseif args[i] == "--store" && i < length(args)
                store_root = args[i+1]
                i += 2
            elseif args[i] == "--static-root" && i < length(args)
                static_root = String(strip(args[i+1]))
                i += 2
            elseif args[i] == "--static"
                static = true
                i += 1
            else
                error("Unknown argument: $(args[i])")
            end
        end

        return (; host, port, store_root, static, static_root)
    end

    (; host, port, store_root, static, static_root) = parse_args(ARGS)
    store = default_store(root=store_root)
    if static
        static_root_abs = abspath(static_root)
        println("Serving static files from: $(static_root_abs)")
        if !isdir(static_root_abs)
            @warn "Static root does not exist; static file serving is enabled but files are unavailable." static_root = static_root_abs
        elseif isempty(readdir(static_root_abs))
            @warn "Static root is empty; static file serving is enabled but no files were found." static_root = static_root_abs
        end
    end
    start_server(; host, port, store, static, static_root, async=false)
  ' -- --host "$API_HOST" --port "$API_PORT" --store "$STORE_ROOT" "${BACKEND_ARGS[@]}" &
  PIDS+=("$!")
fi

echo
if [[ "$START_FRONTEND" -eq 1 ]]; then
  echo "Frontend: http://${FRONTEND_HOST}:${FRONTEND_PORT}"
fi
if [[ "$START_BACKEND" -eq 1 ]]; then
  echo "Backend : http://${API_HOST}:${API_PORT}"
fi
echo "Press Ctrl-C to stop."
echo

wait -n "${PIDS[@]}"
