#!/usr/bin/env bash
set -u

usage() {
  printf '%s\n' 'usage: opencode-away [--check] [opencode arguments...]'
}

require_command() {
  command -v "$1" >/dev/null 2>&1 || {
    printf 'opencode-away: required command not found: %s\n' "$1" >&2
    return 1
  }
}

if [[ ${1-} == --help ]]; then
  usage
  exit 0
fi

check_only=0
if [[ ${1-} == --check ]]; then
  check_only=1
  shift
fi

require_command opencode || exit 127
require_command systemd-inhibit || exit 127
require_command git || exit 127
require_command ps || exit 127
require_command kill || exit 127

if [[ $(systemd-inhibit --help 2>&1) != *handle-lid-switch* ]]; then
  printf '%s\n' 'opencode-away: systemd-inhibit lacks handle-lid-switch' >&2
  exit 3
fi

if ! git rev-parse --show-toplevel >/dev/null 2>&1; then
  printf '%s\n' 'opencode-away: run this command inside a Git worktree' >&2
  exit 2
fi

if ((check_only)); then
  printf '%s\n' 'OpenCode away mode check: OK'
  printf 'repository: %s\n' "$(git rev-parse --show-toplevel)"
  printf 'opencode: %s\n' "$(command -v opencode)"
  printf 'systemd-inhibit: %s\n' "$(command -v systemd-inhibit)"
  exit 0
fi

declare -a suspended_pids=()
cleanup_done=0
child_pid=0

restore_swayidle() {
  local pid
  ((cleanup_done)) && return 0
  cleanup_done=1
  for pid in "${suspended_pids[@]}"; do
    if kill -0 "$pid" 2>/dev/null &&
       [[ $(ps -o comm= -p "$pid" 2>/dev/null) == swayidle ]]; then
      kill -CONT "$pid" 2>/dev/null || true
    fi
  done
  if ((${#suspended_pids[@]})); then
    printf '%s\n' 'swayidle restored'
  fi
}

on_signal() {
  local signal=$1
  if ((child_pid > 0)) && kill -0 "$child_pid" 2>/dev/null; then
    kill -s "$signal" "$child_pid" 2>/dev/null || true
    wait "$child_pid" 2>/dev/null || true
  fi
  restore_swayidle
  trap - "$signal"
  kill -s "$signal" "$$"
}

trap restore_swayidle EXIT
trap 'on_signal HUP' HUP
trap 'on_signal INT' INT
trap 'on_signal TERM' TERM

while read -r pid state; do
  [[ $pid =~ ^[0-9]+$ ]] || continue
  [[ $state == T* ]] && continue
  if kill -STOP "$pid" 2>/dev/null; then
    suspended_pids+=("$pid")
  fi
done < <(ps -C swayidle -o pid=,stat= 2>/dev/null)

printf '%s\n' 'OpenCode away mode'
printf '%s\n' 'sleep inhibited'
printf '%s\n' 'lid switch inhibited'
if ((${#suspended_pids[@]})); then
  printf 'swayidle suspended:'
  printf ' %s' "${suspended_pids[@]}"
  printf '\n'
else
  printf '%s\n' 'swayidle suspended: none active'
fi

export LARDON_OPENCODE_LONG_RUN=1

if [[ -n ${OPENCODE_AWAY_COMMAND-} ]]; then
  child_command=(bash -c "$OPENCODE_AWAY_COMMAND")
else
  child_command=(opencode --auto "$@")
fi

systemd-inhibit \
  --what=sleep:idle:handle-lid-switch \
  --who='OpenCode Long Run' \
  --why='Autonomous Lardon3D development ticket' \
  --mode=block \
  "${child_command[@]}" &
child_pid=$!
wait "$child_pid"
child_status=$?
child_pid=0

restore_swayidle
exit "$child_status"
