#!/usr/bin/env bash

BRT_ACCESS_PID_FILE="${HOME}/.brt/access.pid"
BRT_ACCESS_INFO_FILE="${HOME}/.brt/access.info"
BRT_ACCESS_AUDIT_LOG="${BRT_ACCESS_AUDIT_LOG:-${HOME}/.brt/access.audit.log}"
BRT_ACCESS_ADMIN_SOCK="${BRT_ACCESS_ADMIN_SOCK:-${HOME}/.brt/access.admin.sock}"

brt_access_cleanup() {
  rm -f "$BRT_ACCESS_PID_FILE" "$BRT_ACCESS_INFO_FILE" "$BRT_ACCESS_ADMIN_SOCK"
}

brt_access_port_pids() {
  local port="$1"
  if command -v lsof &>/dev/null; then
    lsof -ti ":${port}" 2>/dev/null || true
  fi
}

brt_access_serve_pids() {
  pgrep -f '[/ ]access\.py serve' 2>/dev/null || true
}

brt_access_kill_pids() {
  local sig="$1"
  shift
  local pid
  for pid in "$@"; do
    [[ -n "$pid" ]] || continue
    kill "-${sig}" "$pid" 2>/dev/null || true
  done
}

brt_access_collect_pids() {
  local port="$1"
  local -a all_pids=() pids=()
  local pid p keep

  if [[ -f "$BRT_ACCESS_PID_FILE" ]]; then
    pid=$(tr -d '[:space:]' < "$BRT_ACCESS_PID_FILE")
    [[ -n "$pid" ]] && all_pids+=("$pid")
  fi

  while IFS= read -r pid; do
    [[ -n "$pid" ]] && all_pids+=("$pid")
  done < <(brt_access_serve_pids)

  if [[ -n "$port" ]]; then
    while IFS= read -r pid; do
      [[ -n "$pid" ]] && all_pids+=("$pid")
    done < <(brt_access_port_pids "$port")
  fi

  for pid in "${all_pids[@]}"; do
    keep=1
    for p in "${pids[@]}"; do
      [[ "$p" == "$pid" ]] && keep=0 && break
    done
    [[ "$keep" -eq 1 ]] && pids+=("$pid")
  done

  if ((${#pids[@]})); then
    printf '%s\n' "${pids[@]}"
  fi
}

brt_access_force_stop() {
  local port="" extra_port="" pid keep killed=0
  local -a ports=() pids=() uniq=() remaining=()

  while [[ $# -gt 0 ]]; do
    case "$1" in
      -p|--port) extra_port="$2"; shift 2 ;;
      *) shift ;;
    esac
  done

  if [[ -f "$BRT_ACCESS_INFO_FILE" ]]; then
    # shellcheck disable=SC1090
    source "$BRT_ACCESS_INFO_FILE"
  fi
  [[ -n "$extra_port" ]] && port="$extra_port"
  [[ -n "$port" ]] && ports+=("$port")
  ports+=(8765)

  for port in "${ports[@]}"; do
    while IFS= read -r pid; do
      [[ -n "$pid" ]] && pids+=("$pid")
    done < <(brt_access_collect_pids "$port")
  done

  for pid in "${pids[@]}"; do
    keep=1
    for port in "${uniq[@]}"; do
      [[ "$port" == "$pid" ]] && keep=0 && break
    done
    [[ "$keep" -eq 1 ]] && uniq+=("$pid")
  done
  pids=()
  if ((${#uniq[@]})); then
    pids=("${uniq[@]}")
  fi

  if [[ ${#pids[@]} -eq 0 ]]; then
    brt_access_cleanup
    brt_warn "No processes found to stop"
    return 0
  fi

  brt_info "Stopping process(es) on access port: ${pids[*]}"
  brt_access_kill_pids TERM "${pids[@]}"
  sleep 0.4
  brt_access_kill_pids KILL "${pids[@]}"
  sleep 0.2
  killed=${#pids[@]}

  for port in "${ports[@]}"; do
    while IFS= read -r pid; do
      [[ -n "$pid" ]] && remaining+=("$pid")
    done < <(brt_access_port_pids "$port")
  done

  if ((${#remaining[@]} > 0)); then
    brt_warn "Port still in use (PID ${remaining[*]})"
    brt_info "Try: kill -9 ${remaining[*]}"
    brt_access_cleanup
    return 1
  fi

  brt_access_cleanup
  brt_ok "Force stopped ${killed} process(es), port free"
}

brt_access_free_port() {
  local port="$1"
  local port_pids live_pid

  port_pids=$(brt_access_port_pids "$port" | tr '\n' ' ')
  live_pid=""
  if [[ -f "$BRT_ACCESS_PID_FILE" ]]; then
    live_pid=$(tr -d '[:space:]' < "$BRT_ACCESS_PID_FILE")
    if [[ -n "$live_pid" ]] && ! kill -0 "$live_pid" 2>/dev/null; then
      live_pid=""
      brt_access_cleanup
    fi
  fi

  if [[ -z "$port_pids" && -z "$live_pid" ]]; then
    return 0
  fi

  if [[ -n "$port_pids" ]]; then
    brt_warn "Port ${port} in use (PID ${port_pids}) — freeing..."
  fi

  brt_access_force_stop -p "$port"
}

brt_access_stop() {
  local force=0
  while [[ $# -gt 0 ]]; do
    case "$1" in
      -f|--force) force=1; shift ;;
      *) shift ;;
    esac
  done

  if [[ "$force" -eq 1 ]]; then
    brt_access_force_stop "$@"
    return
  fi

  local pid=""
  if [[ -f "$BRT_ACCESS_PID_FILE" ]]; then
    pid=$(tr -d '[:space:]' < "$BRT_ACCESS_PID_FILE")
    if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then
      kill "$pid" 2>/dev/null && brt_ok "Stopped access server (PID ${pid})"
      brt_access_cleanup
      return 0
    fi
  fi

  local orphans
  orphans=$(brt_access_serve_pids | tr '\n' ' ')
  if [[ -n "$orphans" ]]; then
    brt_warn "PID file missing/stale but access server still running (${orphans})"
    brt_info "Run: brt -access force-stop"
    return 1
  fi

  brt_access_cleanup
  brt_warn "No access server running"
}

brt_access_start_server() {
  local port="$1"
  local token="$2"

  python3 "${BRT_LIB}/access.py" serve --port "$port" --token "$token" \
    --audit-log "$BRT_ACCESS_AUDIT_LOG" \
    --admin-sock "$BRT_ACCESS_ADMIN_SOCK" \
    > "${HOME}/.brt/access.stdout" 2> "${HOME}/.brt/access.log" &
  local pid=$!
  echo "$pid" > "$BRT_ACCESS_PID_FILE"
  echo "$pid"
}

brt_access_write_info() {
  local token="$1"
  local endpoint="$2"
  local port="$3"
  local pid="$4"

  cat > "$BRT_ACCESS_INFO_FILE" <<EOF
token=${token}
endpoint=${endpoint}
port=${port}
pid=${pid}
audit_log=${BRT_ACCESS_AUDIT_LOG}
admin_sock=${BRT_ACCESS_ADMIN_SOCK}
started=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
EOF
}

brt_access_console() {
  local port="$1"
  local token="$2"
  local endpoint="$3"
  local pid="$4"

  python3 "${BRT_LIB}/access.py" watch-logs \
    --audit-log "$BRT_ACCESS_AUDIT_LOG" \
    --admin-sock "$BRT_ACCESS_ADMIN_SOCK" \
    --interactive \
    --server-pid "$pid" \
    --endpoint "$endpoint" \
    --token "$token" \
    --owns-server
}

brt_access_clear_logs() {
  brt_require python3
  python3 "${BRT_LIB}/access.py" clear-logs --audit-log "$BRT_ACCESS_AUDIT_LOG"
}

brt_access() {
  local subcmd="${1:-}"
  shift || true

  mkdir -p "${HOME}/.brt"

  case "$subcmd" in
    serve)
      local port=8765
      while [[ $# -gt 0 ]]; do
        case "$1" in
          -p|--port) port="$2"; shift 2 ;;
          *) shift ;;
        esac
      done

      brt_require python3

      brt_access_free_port "$port" || exit 1

      local token
      token=$(brt_random_token)

      local pid
      pid=$(brt_access_start_server "$port" "$token")

      sleep 0.4
      if ! kill -0 "$pid" 2>/dev/null; then
        brt_error "Access server failed to start (see ${HOME}/.brt/access.log)"
        brt_access_cleanup
        exit 1
      fi

      local endpoint
      endpoint=$(brt_local_ips | head -1)
      [[ -z "$endpoint" ]] && endpoint="127.0.0.1"
      endpoint="${endpoint}:${port}"

      brt_access_write_info "$token" "$endpoint" "$port" "$pid"

      if [[ -t 0 && -t 1 ]]; then
        brt_access_console "$port" "$token" "$endpoint" "$pid" || true
        if kill -0 "$pid" 2>/dev/null; then
          kill "$pid" 2>/dev/null || true
        fi
        brt_access_cleanup
      else
        echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
        brt_ok "Secure terminal relay is running"
        echo
        echo "  Endpoint:  ${endpoint}"
        echo "  Token:     ${token}"
        echo
        echo "  Connect:   brt -access connect ${endpoint} ${token}"
        echo "  Leave:     brt -access leave   (from another terminal while connected)"
        echo "  Logs:      brt -access logs"
        echo "  Clear:     brt -access clear-logs"
        echo "  Stop:      brt -access stop"
        echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
      fi
      ;;
    logs)
      brt_require python3
      if [[ ! -t 0 || ! -t 1 ]]; then
        if [[ -f "$BRT_ACCESS_AUDIT_LOG" ]]; then
          tail -n "${1:-50}" -f "$BRT_ACCESS_AUDIT_LOG"
        else
          brt_warn "No audit log at ${BRT_ACCESS_AUDIT_LOG}"
        fi
        return 0
      fi
      local server_pid=0
      if [[ -f "$BRT_ACCESS_PID_FILE" ]]; then
        server_pid=$(cat "$BRT_ACCESS_PID_FILE")
        kill -0 "$server_pid" 2>/dev/null || server_pid=0
      fi
      local endpoint="" token=""
      if [[ -f "$BRT_ACCESS_INFO_FILE" ]]; then
        # shellcheck disable=SC1090
        source "$BRT_ACCESS_INFO_FILE"
      fi
      python3 "${BRT_LIB}/access.py" watch-logs \
        --audit-log "$BRT_ACCESS_AUDIT_LOG" \
        --admin-sock "$BRT_ACCESS_ADMIN_SOCK" \
        --interactive \
        --server-pid "${server_pid:-0}" \
        --endpoint "${endpoint:-}" \
        --token "${token:-}"
      ;;
    clients)
      brt_require python3
      python3 "${BRT_LIB}/access.py" clients --admin-sock "$BRT_ACCESS_ADMIN_SOCK"
      ;;
    leave)
      brt_require python3
      python3 "${BRT_LIB}/access.py" leave
      ;;
    disconnect)
      local session_id="${1:-}"
      brt_require python3
      if [[ -z "$session_id" ]]; then
        python3 "${BRT_LIB}/access.py" leave
      else
        python3 "${BRT_LIB}/access.py" disconnect "$session_id" \
          --admin-sock "$BRT_ACCESS_ADMIN_SOCK"
      fi
      ;;
    connect)
      local endpoint="${1:-}"
      local token="${2:-}"
      if [[ -z "$endpoint" || -z "$token" ]]; then
        brt_error "Usage: brt -access connect <host:port> <token>"
        exit 1
      fi
      brt_require python3
      python3 "${BRT_LIB}/access.py" connect "$endpoint" "$token"
      ;;
    status)
      if [[ -f "$BRT_ACCESS_INFO_FILE" ]]; then
        brt_info "Access server info:"
        cat "$BRT_ACCESS_INFO_FILE"
        if [[ -f "$BRT_ACCESS_PID_FILE" ]]; then
          local pid
          pid=$(cat "$BRT_ACCESS_PID_FILE")
          if kill -0 "$pid" 2>/dev/null; then
            brt_ok "Running (PID ${pid})"
            echo
            brt_access clients 2>/dev/null || true
          else
            brt_warn "PID file exists but process not running"
          fi
        fi
      else
        brt_warn "No access server info found"
      fi
      ;;
    clear-logs|clearlogs)
      brt_access_clear_logs
      ;;
    stop|force-stop)
      if [[ "$subcmd" == "force-stop" ]]; then
        brt_access_force_stop "$@"
      else
        brt_access_stop "$@"
      fi
      ;;
    *)
      brt_error "Usage: brt -access <serve|connect|leave|clients|disconnect|logs|clear-logs|status|stop|force-stop>"
      exit 1
      ;;
  esac
}

