#!/bin/bash
# ULCode の金庫から値を取り出す CLI（ULCode の中で起動したエージェント・ターミナル用）。
#
# 使い方:
#   ulcode-vault get <NAME>        値を標準出力へ（例: export FOO=$(ulcode-vault get FOO)）
#   ulcode-vault list              保管している項目の一覧（値は出ない）
#   ulcode-vault set <NAME>        標準入力から値を読んで保存（例: pbpaste | ulcode-vault set FOO）
#
# ULCode が起動時に渡す ULCODE_VAULT_SOCK（ソケットの場所）と ULCODE_VAULT_TOKEN を使い、
# /usr/bin/nc -U で1行送って応答を読むだけ。値やトークンは printf（シェル組み込み）で渡し、
# 他のプロセスの引数には載せない（ps で見えない）。
set -u

usage() {
  cat >&2 <<'USAGE'
使い方:
  ulcode-vault get <NAME>        値を標準出力へ（例: export FOO=$(ulcode-vault get FOO)）
  ulcode-vault list              保管している項目の一覧（値は出ない）
  ulcode-vault set <NAME>        標準入力から値を読んで保存（例: pbpaste | ulcode-vault set FOO）
USAGE
  exit 2
}

fail() {
  printf 'ulcode-vault: %s\n' "$1" >&2
  exit 1
}

if [ -z "${ULCODE_VAULT_SOCK:-}" ]; then
  fail "ULCodeの中で起動したエージェントからだけ使えます"
fi
token="${ULCODE_VAULT_TOKEN:--}"

check_name() {
  [[ "$1" =~ ^[A-Za-z][A-Za-z0-9_]{0,63}$ ]] \
    || fail "名前は英字で始まり、英数字と _ だけの64文字以内にしてください"
}

# 要求を標準入力から受け取り、ソケットへ送って応答をそのまま返す（末尾の改行も保つ）
send() {
  local reply
  reply="$(/usr/bin/nc -U "$ULCODE_VAULT_SOCK" 2>/dev/null; printf x)"
  printf '%s' "${reply%x}"
}

cmd="${1:-}"
case "$cmd" in
  get)
    [ $# -eq 2 ] || usage
    check_name "$2"
    reply="$(printf 'v1 %s get %s\n' "$token" "$2" | send; printf x)"
    ;;
  list)
    [ $# -eq 1 ] || usage
    reply="$(printf 'v1 %s list\n' "$token" | send; printf x)"
    ;;
  set)
    [ $# -eq 2 ] || usage
    check_name "$2"
    value="$(cat; printf x)"
    value="${value%x}"
    value="${value%$'\n'}"
    case "$value" in
      *$'\n'*) fail "改行を含む値は ULCode の画面（設定 → 金庫）から登録してください" ;;
    esac
    [ -n "$value" ] || fail "標準入力から値を渡してください（例: pbpaste | ulcode-vault set $2）"
    reply="$(printf 'v1 %s set %s\n%s\n' "$token" "$2" "$value" | send; printf x)"
    unset value
    ;;
  *)
    usage
    ;;
esac
reply="${reply%x}"

[ -n "$reply" ] || fail "金庫に接続できません（ULCodeが起動しているか確かめてください）"
head="${reply%%$'\n'*}"
case "$head" in
  ok)
    body="${reply#*$'\n'}"
    [ "$body" = "$reply" ] && body=""
    printf '%s' "$body"
    ;;
  err\ *)
    rest="${head#err }"
    fail "${rest#* }"
    ;;
  *)
    fail "金庫から読めない応答が返りました"
    ;;
esac
