#!/usr/bin/env bash
# Profile-aware delegate launcher template.
#
# Installers may copy this to a user-local `delegate` shim. It routes recognized
# AI_PROFILE shells to matching ~/.delegate/config.<profile>.json files, while
# letting known read-only diagnostics run when the profile config is missing.

_delegate_incoming_config="${DELEGATE_CONFIG-}"
_delegate_profile_config="${HOME}/.delegate/config.${AI_PROFILE:-}.json"

_delegate_subcommand() {
  while [ "$#" -gt 0 ]; do
    case "$1" in
      --json|--pass-through|--no-completion-report)
        shift
        ;;
      --cwd|--isolation|--completion-report|--auth-profile|--group)
        [ "$#" -ge 2 ] || return 0
        shift 2
        ;;
      --help|-h|--version)
        printf '%s\n' "$1"
        return 0
        ;;
      --)
        shift
        break
        ;;
      *)
        printf '%s\n' "$1"
        return 0
        ;;
    esac
  done
}

_delegate_launch_help_request() {
  _delegate_launch_cmd="${1:-}"
  [ "$#" -gt 0 ] && shift

  if [ "$_delegate_launch_cmd" = "dry-run" ]; then
    case "${1:-}" in
      --help|-h)
        return 0
        ;;
    esac
    _delegate_launch_cmd="${1:-}"
    [ "$#" -gt 0 ] && shift
  fi

  case "$_delegate_launch_cmd" in
    cursor|codex|kimi|claude|grok|devin|opencode|pi|omp)
      # Parser parity: help is diagnostic only before the mode or immediately
      # after it. Once inline prompt text starts, a later help token is data.
      case "${1:-}" in
        --help|-h)
          return 0
          ;;
        safe|work|call)
          case "${2:-}" in
            --help|-h)
              return 0
              ;;
          esac
          ;;
      esac
      return 1
      ;;
    droid)
      # Droid may place a model alias before the mode, so its last diagnostic
      # help position is one token later than the modeless harnesses.
      case "${1:-}" in
        --help|-h)
          return 0
          ;;
        safe|work|call)
          case "${2:-}" in
            --help|-h)
              return 0
              ;;
          esac
          ;;
        *)
          case "${2:-}" in
            --help|-h)
              return 0
              ;;
            safe|work|call)
              case "${3:-}" in
                --help|-h)
                  return 0
                  ;;
              esac
              ;;
          esac
          ;;
      esac
      return 1
      ;;
    *)
      return 1
      ;;
  esac
}

_delegate_is_readonly_request() {
  while [ "$#" -gt 0 ]; do
    case "$1" in
      --json|--pass-through|--no-completion-report)
        shift
        ;;
      --cwd|--isolation|--completion-report|--auth-profile|--group)
        [ "$#" -ge 2 ] || return 1
        shift 2
        ;;
      *)
        break
        ;;
    esac
  done
  _cmd="${1:-}"
  [ "$#" -gt 0 ] && shift
  case "$_cmd" in
    cursor|droid|codex|kimi|claude|grok|devin|opencode|pi|omp|dry-run)
      _delegate_launch_help_request "$_cmd" "$@" && return 0
      return 1
      ;;
  esac
  # Non-launch command parsers treat help as diagnostic wherever accepted.
  for _delegate_help_arg in "$@"; do
    case "$_delegate_help_arg" in
      --help|-h)
        return 0
        ;;
    esac
  done
  case "$_cmd" in
    profiles|runs|ps|run-output|describe|snapshot|agent-help|personas|help|--help|-h|--version)
      return 0
      ;;
    models)
      for _delegate_model_arg in "$@"; do
        if [ "$_delegate_model_arg" = "--live" ]; then
          return 1
        fi
      done
      return 0
      ;;
    capabilities)
      # Scan every remaining arg for a `refresh` positional (not just $1) so
      # `capabilities --verbose refresh` is still classified as a mutation.
      for _delegate_cap_arg in "$@"; do
        if [ "$_delegate_cap_arg" = "refresh" ]; then
          return 1
        fi
      done
      return 0
      ;;
    mail)
      while [ "$#" -gt 0 ]; do
        case "$1" in
          --json)
            shift
            ;;
          --)
            return 1
            ;;
          -*)
            return 1
            ;;
          *)
            break
            ;;
        esac
      done
      case "${1:-}" in
        inbox|status|watch)
          return 0
          ;;
        read)
          for _delegate_mail_arg in "$@"; do
            [ "$_delegate_mail_arg" = "--" ] && break
            [ "$_delegate_mail_arg" = "--peek" ] && return 0
          done
          return 1
          ;;
        *)
          return 1
          ;;
      esac
      ;;
    worktree)
      case "${1:-}" in
        show|list)
          return 0
          ;;
        *)
          return 1
          ;;
      esac
      ;;
    workflow)
      # The parser consumes --json tokens before the action, so the action is
      # the first non-option token after `workflow`; trailing flags/paths
      # never decide classification.
      while [ "$#" -gt 0 ]; do
        case "$1" in
          --json)
            shift
            ;;
          *)
            break
            ;;
        esac
      done
      # Parity with profile_guard.READ_ONLY_WORKFLOW_ACTIONS is enforced by
      # tests; update both together.
      case "${1:-}" in
        check|status|watch|events|result|wait|list)
          return 0
          ;;
        *)
          return 1
          ;;
      esac
      ;;
    *)
      return 1
      ;;
  esac
}

_delegate_profile_fix_message() {
  cat >&2 <<EOF
delegate: AI_PROFILE=${AI_PROFILE} but ${_delegate_profile_config} is missing/unreadable; refusing to run a launch or mutation command on the wrong account.
Fix: create the profile config from config.example.json, or run 'env -u AI_PROFILE delegate config sync-profiles' to materialize missing profile overlays.
Temporary bypass: 'env -u AI_PROFILE delegate ...' uses the base config (work Claude, ambient Codex).
EOF
}

if [ -n "${AI_PROFILE:-}" ]; then
  case "${AI_PROFILE}" in
    personal|work)
      if [ ! -r "$_delegate_profile_config" ]; then
        _delegate_cmd="$(_delegate_subcommand "$@")"
        if _delegate_is_readonly_request "$@"; then
          echo "delegate: warning: AI_PROFILE=${AI_PROFILE} but ${_delegate_profile_config} is missing/unreadable; continuing because '${_delegate_cmd}' is read-only. Launch and mutation commands remain blocked until the profile config exists." >&2
        else
          _delegate_profile_fix_message
          exit 1
        fi
      else
        export DELEGATE_CONFIG="$_delegate_profile_config"
        _delegate_keys="${HOME}/.ai-profiles/${AI_PROFILE}/keys.zsh"
        # ponytail: current keys.zsh files are plain exports; switch to parsing if
        # they ever need zsh-only syntax.
        [ -f "$_delegate_keys" ] && . "$_delegate_keys"
        if [ -n "$_delegate_incoming_config" ]; then
          export DELEGATE_CONFIG="$_delegate_incoming_config"
        fi
      fi
      ;;
    *)
      echo "delegate: AI_PROFILE='${AI_PROFILE}' is not a recognized profile (work|personal); running on the base account" >&2
      ;;
  esac
fi

if [ -n "${DELEGATE_SHIM_PY:-}" ]; then
  exec python3 "$DELEGATE_SHIM_PY" "$@"
fi
exec python3 -m delegate_agent.cli "$@"
