#!/usr/bin/env bash
#
# _jira-auth.sh  -  one resolution of host + token, and one way to call Jira.
#
# WHY THIS EXISTS
#
# The same twelve lines were written twice (`jira-publish.sh`, `issue-fetcher.sh`)
# and a third writer was about to make it three. Duplicated auth does not stay
# duplicated: it drifts, and the copy that drifts is the one nobody is looking at.
#
# Today only `analysis-jira-write.sh` sources this. The two older callers still
# carry their own resolution - `issue-fetcher.sh` resolves per-account token keys
# this helper does not model yet - so this is where new callers go, not a
# consolidation that has already happened.
# Worse, the part most worth getting right is the part most easily retyped badly -
# the token goes to curl through a `-K` config on process substitution so it never
# reaches argv, a log, or `ps`. A second-hand copy of that idiom is a leak waiting
# for the first person who simplifies it.
#
# Sourced, never executed. The leading underscore marks it: it is a library for
# the scripts beside it, not a command.
#
#   . "$(dirname "$0")/_jira-auth.sh"
#   jira_auth_resolve || exit 4      # sets JIRA_API_HOST and JIRA_API_TOKEN
#   jira_api GET /rest/api/2/myself
#
# Resolution, in order, for each of the two values:
#   host   $JIRA_HOST, $ACCOUNT_JIRA_HOST, prefs .global.hosts.jira
#   token  $JIRA_TOKEN, else credential-store.sh get <key>, where the key is
#          $JIRA_TOKEN_KEY, $ACCOUNT_JIRA_TOKEN_KEY, or
#          prefs .global.keychainMapping.jira
#
# Exit contract: `jira_auth_resolve` returns 0 when both resolved, 4 when either
# did not, having already said which on stderr. 4 is the same code both callers
# already used for "could not resolve", so nothing downstream changes meaning.

# shellcheck shell=bash

JIRA_AUTH_PREFS="${JIRA_AUTH_PREFS:-$HOME/.claude/multi-agent-preferences.json}"

_jira_auth_pref() {  # _jira_auth_pref <jq path> -> value or empty
  [ -f "$JIRA_AUTH_PREFS" ] || { printf ''; return 0; }
  jq -r "$1 // empty" "$JIRA_AUTH_PREFS" 2>/dev/null || printf ''
}

_jira_auth_store() {  # locate credential-store.sh from lib/ or the install
  local here
  here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  for cand in "$here/credential-store.sh" "$HOME/.claude/lib/credential-store.sh"; do
    [ -f "$cand" ] && { printf '%s' "$cand"; return 0; }
  done
  return 1
}

jira_auth_resolve() {
  JIRA_API_HOST="${JIRA_HOST:-${ACCOUNT_JIRA_HOST:-}}"
  [ -n "$JIRA_API_HOST" ] || JIRA_API_HOST="$(_jira_auth_pref '.global.hosts.jira')"
  if [ -z "$JIRA_API_HOST" ]; then
    echo "ERR: no Jira host: set JIRA_HOST or prefs .global.hosts.jira" >&2
    return 4
  fi
  # A host is a host, whatever the caller pasted.
  JIRA_API_HOST="${JIRA_API_HOST#https://}"
  JIRA_API_HOST="${JIRA_API_HOST#http://}"
  JIRA_API_HOST="${JIRA_API_HOST%/}"

  JIRA_API_TOKEN="${JIRA_TOKEN:-}"
  if [ -z "$JIRA_API_TOKEN" ]; then
    local key store
    key="${JIRA_TOKEN_KEY:-${ACCOUNT_JIRA_TOKEN_KEY:-}}"
    [ -n "$key" ] || key="$(_jira_auth_pref '.global.keychainMapping.jira')"
    if [ -z "$key" ]; then
      echo "ERR: no Jira token: set JIRA_TOKEN or map prefs .global.keychainMapping.jira" >&2
      return 4
    fi
    store="$(_jira_auth_store)" || {
      echo "ERR: credential-store.sh not found next to lib/ or in ~/.claude/lib" >&2
      return 4
    }
    JIRA_API_TOKEN="$(bash "$store" get "$key" 2>/dev/null || printf '')"
    if [ -z "$JIRA_API_TOKEN" ]; then
      echo "ERR: Jira token not in the credential store under: $key" >&2
      return 4
    fi
  fi
  return 0
}

# The token reaches curl only through a -K config on process substitution: never
# argv, never a log, never `ps`. Every caller goes through here so that stays
# true in one place instead of three.
_jira_auth_cfg() { printf 'header = "Authorization: Bearer %s"\n' "$1"; }

jira_api() {  # jira_api <METHOD> <path> [curl args...]
  local method="$1" path="$2"; shift 2
  curl -sS -m 30 -K <(_jira_auth_cfg "$JIRA_API_TOKEN") \
    -H "Content-Type: application/json" \
    -X "$method" "https://$JIRA_API_HOST$path" "$@"
}
