#!/bin/bash
# khaosd-ctl — daemon lifecycle helper for Khaos Machine
# Uses launchctl (macOS) or systemctl (Linux) to manage khaosd.
set -euo pipefail

LABEL="studio.khaos.khaosd"
PLIST="/Library/LaunchAgents/${LABEL}.plist"
RUNTIME_JSON="${HOME}/.khaos/runtime.json"
KHAOSD_BIN="/usr/local/bin/khaosd"

usage() {
  cat <<EOF
Usage: khaosd-ctl <command>

Commands:
  start          Start the khaosd daemon
  stop           Stop the khaosd daemon
  restart        Restart the khaosd daemon
  status         Show daemon status (PID, port, version)
  logs           Follow the daemon console log
  logs --errors  Show recent error entries only

EOF
  exit 1
}

# --- platform helpers --------------------------------------------------------

is_macos() { [ "$(uname -s)" = "Darwin" ]; }

macos_service_target() { echo "gui/$(id -u)/${LABEL}"; }

macos_agent_loaded() {
  launchctl print "$(macos_service_target)" >/dev/null 2>&1
}

macos_agent_running() {
  local state
  state=$(launchctl print "$(macos_service_target)" 2>/dev/null | awk '/^\tstate =/{print $3; exit}')
  [ "$state" = "running" ]
}

linux_unit_exists() {
  systemctl --user cat khaosd.service >/dev/null 2>&1
}

# --- runtime.json reader -----------------------------------------------------

read_runtime() {
  if [ -f "$RUNTIME_JSON" ]; then
    local pid port version
    pid=$(grep -o '"pid": *[0-9]*' "$RUNTIME_JSON" | grep -o '[0-9]*')
    port=$(grep -o '"port": *[0-9]*' "$RUNTIME_JSON" | grep -o '[0-9]*')
    version=$(grep -o '"version": *"[^"]*"' "$RUNTIME_JSON" | sed 's/.*"\([^"]*\)"$/\1/')
    echo "$pid $port $version"
  fi
}

# --- commands ----------------------------------------------------------------

do_start() {
  if is_macos; then
    if [ -f "$PLIST" ] && macos_agent_loaded; then
      launchctl kickstart "$(macos_service_target)" 2>/dev/null || true
      echo "khaosd starting via LaunchAgent"
    else
      echo "LaunchAgent not loaded — starting khaosd directly"
      nohup "$KHAOSD_BIN" >/dev/null 2>&1 &
    fi
  else
    if linux_unit_exists; then
      systemctl --user start khaosd
      echo "khaosd starting via systemd"
    else
      echo "systemd unit not found — starting khaosd directly"
      nohup "$KHAOSD_BIN" >/dev/null 2>&1 &
    fi
  fi
}

do_stop() {
  if is_macos; then
    if [ -f "$PLIST" ] && macos_agent_loaded; then
      launchctl kill SIGTERM "$(macos_service_target)" 2>/dev/null || true
      echo "khaosd stop requested via LaunchAgent"
    else
      # Fallback: send SIGTERM to PID from runtime.json
      local info
      info=$(read_runtime)
      if [ -n "$info" ]; then
        local pid
        pid=$(echo "$info" | awk '{print $1}')
        if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
          kill -TERM "$pid" 2>/dev/null || true
          echo "khaosd (pid $pid) sent SIGTERM"
        fi
      else
        echo "khaosd is not running"
      fi
    fi
  else
    if linux_unit_exists; then
      systemctl --user stop khaosd
      echo "khaosd stopped via systemd"
    else
      local info
      info=$(read_runtime)
      if [ -n "$info" ]; then
        local pid
        pid=$(echo "$info" | awk '{print $1}')
        if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
          kill -TERM "$pid" 2>/dev/null || true
          echo "khaosd (pid $pid) sent SIGTERM"
        fi
      else
        echo "khaosd is not running"
      fi
    fi
  fi
}

do_restart() {
  do_stop
  sleep 2
  do_start
}

do_status() {
  local running="no"
  local info pid port version

  # Check via service manager first
  if is_macos; then
    if [ -f "$PLIST" ] && macos_agent_loaded && macos_agent_running; then
      running="yes (LaunchAgent)"
    fi
  else
    if linux_unit_exists && systemctl --user is-active --quiet khaosd 2>/dev/null; then
      running="yes (systemd)"
    fi
  fi

  # Read runtime.json for details
  info=$(read_runtime)
  if [ -n "$info" ]; then
    pid=$(echo "$info" | awk '{print $1}')
    port=$(echo "$info" | awk '{print $2}')
    version=$(echo "$info" | awk '{print $3}')

    # Validate PID is alive
    if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
      [ "$running" = "no" ] && running="yes (direct)"
      echo "Status:  running"
      echo "PID:     $pid"
      echo "Port:    $port"
      echo "Version: $version"
      echo "Managed: $running"
      return 0
    else
      # Stale runtime.json
      echo "Status:  stopped (stale runtime.json found)"
      return 1
    fi
  fi

  if [ "$running" != "no" ]; then
    echo "Status:  starting (no runtime.json yet)"
    return 0
  fi

  echo "Status:  stopped"
  return 1
}

# --- main --------------------------------------------------------------------

[ $# -lt 1 ] && usage

do_logs() {
  local log_dir="${HOME}/.khaos/logs"
  local console_log="$log_dir/khaosd-console.log"

  if [ ! -d "$log_dir" ]; then
    echo "Log directory not found: $log_dir"
    echo "Falling back to console API..."
    # Fallback: try the API
    local info
    info=$(read_runtime)
    if [ -n "$info" ]; then
      local port
      port=$(echo "$info" | awk '{print $2}')
      if [ -n "$port" ]; then
        # Dump raw NDJSON from console API (pipe through jq for formatting)
        curl -s "http://127.0.0.1:${port}/api/console/entries" 2>/dev/null
      fi
    fi
    return 0
  fi

  if [ "${2:-}" = "--errors" ]; then
    if [ -f "$console_log" ]; then
      grep '"level":"error"' "$console_log" 2>/dev/null | tail -50
    else
      echo "No console log found yet at $console_log"
      echo "Hint: persistent console logging requires khaosd with file-backed console (coming soon)"
    fi
  else
    if [ -f "$console_log" ]; then
      tail -f "$console_log"
    else
      echo "No console log found yet at $console_log"
      echo "Hint: persistent console logging requires khaosd with file-backed console (coming soon)"
      echo ""
      echo "Current logs available:"
      ls -la "$log_dir"/ 2>/dev/null || echo "  (empty)"
    fi
  fi
}

case "${1}" in
  start)   do_start   ;;
  stop)    do_stop    ;;
  restart) do_restart ;;
  status)  do_status  ;;
  logs)    do_logs "${2:-}" ;;
  *)       usage      ;;
esac
