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

REPO_DIR="/home/agent/.hermes/repos/FinanceManager"
RUNTIME_DIR="${JARVIS_FINANCE_RUNTIME_DIR:-$HOME/jarvis_runtime/finance-system}"
LOG_DIR="$RUNTIME_DIR/logs"
BACKEND_PID_FILE="$LOG_DIR/finance_backend.pid"
FRONTEND_PID_FILE="$LOG_DIR/finance_frontend.pid"
BACKEND_LOG="$LOG_DIR/finance_backend.log"
FRONTEND_LOG="$LOG_DIR/finance_frontend.log"
BACKEND_HOST="${BACKEND_HOST:-0.0.0.0}"
BACKEND_PORT="${BACKEND_PORT:-8000}"
FRONTEND_PORT="${FRONTEND_PORT:-5173}"
KILL_EXISTING=0

usage() {
  cat <<'USAGE'
Usage: scripts/start_vue_dashboard.sh [--kill-existing]

Starts FinanceManager FastAPI backend and Vue frontend, then verifies health.
Logs and PID files are written under the external runtime log directory.
USAGE
}

for arg in "$@"; do
  case "$arg" in
    --kill-existing) KILL_EXISTING=1 ;;
    -h|--help) usage; exit 0 ;;
    *) echo "Unknown argument: $arg" >&2; usage; exit 2 ;;
  esac
done

require_dir() {
  if [[ ! -d "$1" ]]; then
    echo "Missing directory: $1" >&2
    exit 1
  fi
}

port_in_use() {
  python - "$1" <<'PY'
import socket, sys
port = int(sys.argv[1])
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    sys.exit(0 if s.connect_ex(("127.0.0.1", port)) == 0 else 1)
PY
}

wait_http() {
  local url="$1"
  local label="$2"
  for _ in $(seq 1 50); do
    if curl -fsS -m 2 "$url" >/dev/null 2>&1; then
      echo "$label healthcheck OK: $url"
      return 0
    fi
    sleep 0.2
  done
  echo "$label healthcheck FAILED: $url" >&2
  return 1
}

stop_from_pid_file() {
  local pid_file="$1"
  if [[ -f "$pid_file" ]]; then
    local pid
    pid="$(tr -cd '0-9' < "$pid_file" || true)"
    if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then
      kill "$pid" 2>/dev/null || true
      for _ in $(seq 1 20); do kill -0 "$pid" 2>/dev/null || break; sleep 0.2; done
      kill -9 "$pid" 2>/dev/null || true
    fi
    rm -f "$pid_file"
  fi
}

kill_port() {
  local port="$1"
  if command -v fuser >/dev/null 2>&1; then
    local pids
    pids="$(fuser -n tcp "$port" 2>/dev/null || true)"
    [[ -n "$pids" ]] && kill $pids 2>/dev/null || true
    sleep 0.5
    pids="$(fuser -n tcp "$port" 2>/dev/null || true)"
    [[ -n "$pids" ]] && kill -9 $pids 2>/dev/null || true
  fi
}

require_dir "$REPO_DIR"
require_dir "$RUNTIME_DIR"
if [[ ! -f "$RUNTIME_DIR/venv/bin/activate" ]]; then
  echo "Missing Python venv: $RUNTIME_DIR/venv" >&2
  echo "Create/restore the FinanceManager runtime venv first." >&2
  exit 1
fi
if [[ ! -x "$REPO_DIR/frontend/node_modules/.bin/vite" ]]; then
  echo "Missing Vite dependency. Run: cd $REPO_DIR/frontend && npm install" >&2
  exit 1
fi
mkdir -p "$LOG_DIR"

if [[ "$KILL_EXISTING" == "1" ]]; then
  stop_from_pid_file "$BACKEND_PID_FILE"
  stop_from_pid_file "$FRONTEND_PID_FILE"
  kill_port "$BACKEND_PORT"
  kill_port "$FRONTEND_PORT"
fi

if port_in_use "$BACKEND_PORT"; then
  echo "Port $BACKEND_PORT is already in use. Stop the existing backend or run with --kill-existing." >&2
  exit 1
fi
if port_in_use "$FRONTEND_PORT"; then
  echo "Port $FRONTEND_PORT is already in use. Stop the existing frontend or run with --kill-existing." >&2
  exit 1
fi

cd "$REPO_DIR"
# shellcheck source=/dev/null
source "$RUNTIME_DIR/venv/bin/activate"
export JARVIS_FINANCE_RUNTIME_DIR="$RUNTIME_DIR"
unset JARVIS_FINANCE_DB_PATH

: > "$BACKEND_LOG"
: > "$FRONTEND_LOG"

echo "Starting FastAPI backend on http://$BACKEND_HOST:$BACKEND_PORT"
PYTHONPATH=src uvicorn jarvis_finance.api.main:app --host "$BACKEND_HOST" --port "$BACKEND_PORT" \
  > "$BACKEND_LOG" 2>&1 &
BACKEND_PID=$!
echo "$BACKEND_PID" > "$BACKEND_PID_FILE"
wait_http "http://127.0.0.1:$BACKEND_PORT/api/health" "Backend"

cd "$REPO_DIR/frontend"
TAILSCALE_DNS="${TAILSCALE_DNS:-}"
TAILSCALE_IP="${TAILSCALE_IP:-}"
if [[ -z "$TAILSCALE_DNS" ]] && command -v tailscale >/dev/null 2>&1; then
  TAILSCALE_DNS="$(tailscale status --json 2>/dev/null | python -c 'import json,sys; data=json.load(sys.stdin); print(data.get("Self",{}).get("DNSName","").rstrip("."))' 2>/dev/null || true)"
fi
if [[ -z "$TAILSCALE_IP" ]] && command -v tailscale >/dev/null 2>&1; then
  TAILSCALE_IP="$(tailscale ip -4 2>/dev/null | head -n1 || true)"
fi
TAILSCALE_HOST="${TAILSCALE_HOST:-${TAILSCALE_DNS:-$TAILSCALE_IP}}"
PUBLIC_API_ORIGIN="${VITE_API_BASE_URL:-}"
if [[ -z "$PUBLIC_API_ORIGIN" && -n "$TAILSCALE_HOST" ]]; then
  PUBLIC_API_ORIGIN="http://$TAILSCALE_HOST:$BACKEND_PORT"
fi
if [[ -z "$PUBLIC_API_ORIGIN" ]]; then
  PUBLIC_API_ORIGIN="http://127.0.0.1:$BACKEND_PORT"
fi
export VITE_API_BASE_URL="$PUBLIC_API_ORIGIN"
if [[ -n "$TAILSCALE_HOST" ]]; then
  allowed="$TAILSCALE_HOST"
  [[ -n "$TAILSCALE_IP" && "$allowed" != *"$TAILSCALE_IP"* ]] && allowed="$allowed,$TAILSCALE_IP"
  [[ -n "$TAILSCALE_DNS" && "$allowed" != *"$TAILSCALE_DNS"* ]] && allowed="$allowed,$TAILSCALE_DNS"
  export __VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS="${__VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS:-$allowed}"
fi

echo "Starting Vue frontend on http://0.0.0.0:$FRONTEND_PORT"
echo "Frontend API base: $VITE_API_BASE_URL"
npm run dev -- --host 0.0.0.0 --port "$FRONTEND_PORT" \
  > "$FRONTEND_LOG" 2>&1 &
FRONTEND_PID=$!
echo "$FRONTEND_PID" > "$FRONTEND_PID_FILE"
wait_http "http://127.0.0.1:$FRONTEND_PORT/" "Frontend"
if [[ -n "$TAILSCALE_IP" ]]; then
  wait_http "http://$TAILSCALE_IP:$FRONTEND_PORT/" "Tailscale frontend" || true
fi

printf 'Backend PID: %s\n' "$BACKEND_PID"
printf 'Frontend PID: %s\n' "$FRONTEND_PID"
printf 'Backend: http://127.0.0.1:%s\n' "$BACKEND_PORT"
printf 'Frontend: http://127.0.0.1:%s\n' "$FRONTEND_PORT"
[[ -n "$TAILSCALE_IP" ]] && printf 'Tailscale Frontend: http://%s:%s\n' "$TAILSCALE_IP" "$FRONTEND_PORT"
[[ -n "$TAILSCALE_DNS" ]] && printf 'Tailscale DNS Frontend: http://%s:%s\n' "$TAILSCALE_DNS" "$FRONTEND_PORT"
echo "Logs:"
printf '  %s\n' "$BACKEND_LOG"
printf '  %s\n' "$FRONTEND_LOG"
