#!/usr/bin/env bash
# Single entry point for the dockerised local stack.
set -euo pipefail

PACKAGE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export RUN_PACKAGE_DIR="${PACKAGE_DIR}"
# shellcheck source=scripts/workspace.sh
source "${PACKAGE_DIR}/scripts/workspace.sh"
resolve_workspace "${RUN_WORKSPACE_DIR:-${PWD}}"
SCRIPTS="${PACKAGE_DIR}/scripts"

# How the person invoked this, so every hint names a command they can retype.
# The global CLI sets RUN_STACK_CLI when it forwards a command.
RUN_CMD="${RUN_STACK_CLI:-run-stack}"
export RUN_CMD

usage() {
  cat <<USAGE
Local stack runner

Usage: ${RUN_CMD} <command> [args]

Setup
  init [--file f]      Write .run/run.config.json and .run/.env (capabilities, apps, ports)
  init --update        Find apps added to the workspace since the last run and
                       add them; says so when there is nothing new
                       --file <json> takes answers from a file, --yes every default

Lifecycle
  up [service...]      Build if needed and start the stack (default command)
  run [service...]     Alias for up
  up --essential       Start only services listed under "essential" in config
  down [service...]    Stop everything, or just the named services (keeps data)
  restart [--build] [--essential] [service...]
                       Stop then start (down + up). --build rebuilds images
  rebuild              Rebuild images from scratch and recreate containers
  clean                Stop and DELETE all volumes (db, redis, node_modules)

Inspection
  commands [--raw]     List every CLI command in a table
  apps                 List configured apps (backend, web, mobile, …)
  list                 Alias for apps
  services [--raw]     List compose services (and status when Docker is up)
  ps                   Service status
  ports [--show]       Host ports + env URLs table (keep base URLs in sync)
  logs [service...]    Follow logs
  shell [service]      Shell into a container (default: backend)

Backend
  backend <args...>    Run any command inside the backend container
  migrate              Run pending migrations
  seed                 Run database seeders
  fresh                Rebuild the schema and seed it (destroys data)
  artisan <args...>    php artisan ...   (BACKEND_STACK=laravel)
  composer <args...>   composer ...      (BACKEND_STACK=laravel)

Frontend
  pnpm <args...>       pnpm ... inside the frontend workspace

Mobile ([app] defaults to MOBILE_APP; name any mobile app in EXTRA_APPS)
  ios [app]            Open a mobile app in the iOS Simulator
  android [app]        Open a mobile app on an Android emulator
  device [target] [app]  Open on a USB phone, or print the Expo Go URL
  mobile [--build] [app] Restart that app's Metro (and its deps for the built-in)
  reload [--clear] [app] Metro /status + /reload; --clear wipes caches (no Docker restart)
  prebuild [app] [args...]  expo prebuild (Expo apps only; pass --clean etc.)
  sync-mobile-port [app] Sync the Metro port into the mobile app configs
  bundler [ios|android] [app]  Point the simulator at Metro (Expo deep link / CMD+D)

Desktop
  desktop              Launch the Electron / Tauri shell on the host

Deploy
  deploy <target> [env]  Deploy web, mobile or desktop (env: staging by default)

Dashboard
  dash                 Open the status dashboard in a browser

Services: postgres mysql redis mailpit minio dashboard backend queue scheduler
          frontend-deps frontend-packages web admin landing desktop
          mobile-deps mobile-packages mobile-client

Default URLs: dashboard :8090  web :5173  admin :5174  landing :5175
              desktop :5176  api :8000  mailpit :8025  metro :8081

The backend runs either a Laravel or a Node app: set BACKEND_STACK in .run/run.config.json
Everything (ports, repository paths, app names, which services run at all) is
configured there — run ${RUN_CMD} init to generate it. Disable capabilities with
RUN_ADMIN / RUN_LANDING / RUN_MOBILE / RUN_DESKTOP / RUN_REDIS / RUN_MAILPIT /
RUN_MINIO=false, and pick the database with DB_ENGINE=postgres|mysql|none.
USAGE
}

CMD="${1:-up}"
[ $# -gt 0 ] && shift || true

case "${CMD}" in
  init)      exec bash "${SCRIPTS}/init.sh" "$@" ;;
  up)        exec bash "${SCRIPTS}/up.sh" "$@" ;;
  run)       exec bash "${SCRIPTS}/up.sh" "$@" ;;
  down)      exec bash "${SCRIPTS}/down.sh" "$@" ;;
  restart)   exec bash "${SCRIPTS}/restart.sh" "$@" ;;
  rebuild)   exec bash "${SCRIPTS}/rebuild.sh" "$@" ;;
  clean)     exec bash "${SCRIPTS}/clean.sh" "$@" ;;
  ps|status) exec bash "${SCRIPTS}/ps.sh" "$@" ;;
  commands)  exec bash "${SCRIPTS}/commands.sh" "$@" ;;
  apps|list) exec bash "${SCRIPTS}/apps.sh" "$@" ;;
  services)  exec bash "${SCRIPTS}/services.sh" "$@" ;;
  ports)     exec bash "${SCRIPTS}/ports-show.sh" "$@" ;;
  logs)      exec bash "${SCRIPTS}/logs.sh" "$@" ;;
  shell|sh)  exec bash "${SCRIPTS}/shell.sh" "$@" ;;
  backend)   exec bash "${SCRIPTS}/backend.sh" "$@" ;;
  artisan)   exec bash "${SCRIPTS}/artisan.sh" "$@" ;;
  composer)  exec bash "${SCRIPTS}/composer.sh" "$@" ;;
  layout-migrate) exec bash "${SCRIPTS}/layout-migrate.sh" "$@" ;;
  migrate)   exec bash "${SCRIPTS}/migrate.sh" "$@" ;;
  seed)      exec bash "${SCRIPTS}/seed.sh" "$@" ;;
  fresh)     exec bash "${SCRIPTS}/fresh.sh" "$@" ;;
  pnpm)      exec bash "${SCRIPTS}/pnpm.sh" "$@" ;;
  dash|dashboard) exec bash "${SCRIPTS}/dash.sh" "$@" ;;
  ios)       exec bash "${SCRIPTS}/ios.sh" "$@" ;;
  android)   exec bash "${SCRIPTS}/android.sh" "$@" ;;
  device)    exec bash "${SCRIPTS}/device.sh" "$@" ;;
  mobile)    exec bash "${SCRIPTS}/mobile.sh" "$@" ;;
  reload)    exec bash "${SCRIPTS}/reload.sh" "$@" ;;
  prebuild)  exec bash "${SCRIPTS}/prebuild.sh" "$@" ;;
  desktop)   exec bash "${SCRIPTS}/desktop.sh" "$@" ;;
  deploy)    exec bash "${SCRIPTS}/deploy.sh" "$@" ;;
  sync-mobile-port) exec bash "${SCRIPTS}/sync-mobile-port.sh" "$@" ;;
  bundler|configure-bundler) exec bash "${SCRIPTS}/configure-bundler.sh" "$@" ;;
  help|-h|--help) usage ;;
  *)
    echo "unknown command: ${CMD}" >&2
    echo
    usage
    exit 1
    ;;
esac
