#!/bin/bash

# omarchy:hidden=true
# omarchy:summary=Review a blocked USB device authorization request

set -euo pipefail

token="${1:-}"
if [[ ! $token =~ ^request-[0-9a-f]{64}$ ]]; then
  echo "This USB authorization request is invalid or expired." >&2
  exit 1
fi

request="$HOME/.local/state/omarchy/usb-authorization/requests/$token.json"
if [[ ! -f $request || -L $request ]]; then
  echo "This USB authorization request is no longer available." >&2
  exit 1
fi

id=$(jq -er '.id | select(test("^[0-9]+$"))' "$request")
expected_rule=$(jq -er '.rule | select(type == "string" and length > 0)' "$request")
read_blocked_rule() {
  local line

  while IFS= read -r line; do
    if [[ $line == "$id: "* ]]; then
      printf '%s\n' "${line#"$id: "}"
      return 0
    fi
  done < <(usbguard list-devices --blocked)

  return 1
}

current_rule=$(read_blocked_rule || true)

if [[ -z $current_rule || $current_rule != "$expected_rule" ]]; then
  rm -f "$request"
  echo "That USB device was removed or changed. Connect it again to review it." >&2
  exit 1
fi

gum style --foreground 212 --bold "Blocked USB accessory"
echo
echo "The following details come from the device and can be forged:"
printf '%s\n' "$current_rule" | LC_ALL=C tr -c '\11\12\15\40-\176' '?'
echo

choice=$(gum choose \
  "Allow once" \
  "Always allow this device" \
  "Keep blocked") || exit 130

if [[ $choice != "Keep blocked" ]]; then
  current_rule=$(read_blocked_rule || true)
  if [[ -z $current_rule || $current_rule != "$expected_rule" ]]; then
    rm -f "$request"
    echo "That USB device was removed or changed. Connect it again to review it." >&2
    exit 1
  fi
fi

approval_failed() {
  echo "Could not confirm USB approval. The request has been kept; try again." >&2
  exit 1
}

case "$choice" in
"Allow once" | "Always allow this device")
  # Target the complete identity rule instead of USBGuard's numeric ID. IDs can
  # be reassigned when the daemon restarts while the review dialog is open.
  options=()
  if [[ $choice == "Always allow this device" ]]; then
    options+=(--permanent)
  fi
  usbguard allow-device "${options[@]}" "$expected_rule" || approval_failed

  # Rule-based USBGuard commands swallow applyDevicePolicy exceptions and can
  # return success without authorizing anything. Verify the exact device.
  allowed_rule="allow ${expected_rule#block }"
  allowed=$(usbguard list-devices --allowed) || approval_failed
  grep -Fqx -- "$id: $allowed_rule" <<<"$allowed" || approval_failed

  if [[ $choice == "Always allow this device" ]]; then
    # Let USBGuard match policy rules: saved rules can omit the device's port.
    # --show-devices indents the devices matching each policy rule.
    policy=$(usbguard list-rules --show-devices) || approval_failed
    policy_allows=0
    matched=0
    while IFS= read -r line; do
      if [[ $line =~ ^[0-9]+:[[:space:]] ]]; then
        policy_allows=0
        if [[ $line =~ ^[0-9]+:[[:space:]]allow[[:space:]] ]]; then
          policy_allows=1
        fi
      elif (( policy_allows )) && [[ $line == $'\t'"$id: $allowed_rule" ]]; then
        matched=1
        break
      fi
    done <<<"$policy"
    (( matched )) || approval_failed
    echo "USB accessory added to the trusted policy."
  else
    echo "USB accessory allowed until it is disconnected."
  fi
  ;;
"Keep blocked")
  echo "USB accessory remains blocked."
  ;;
esac

rm -f "$request"
