#!/usr/bin/env bash

set -euo pipefail

readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly DEFAULT_INBOX_SKILL_PATH="$(cd "${SCRIPT_DIR}/../../inbox" && pwd)"

dispatch_json=""
db_path=""
inbox_skill_path="${DEFAULT_INBOX_SKILL_PATH}"
extra_instructions_file=""

usage() {
  cat <<'EOF'
Usage: orch-worker-brief --dispatch-json PATH --db PATH [--inbox-skill-path PATH] [--extra-instructions-file PATH]

Read an `orch dispatch --json` response and render a standardized worker prompt
for a Codex sub-agent that should execute the assigned inbox thread.

Required:
  --dispatch-json PATH         Path to the saved `orch dispatch --json` response
  --db PATH                    Shared SQLite DB path for both orch and inbox

Optional:
  --inbox-skill-path PATH      Path to the inbox skill bundle. Defaults to the
                               sibling project-local skill at skills/inbox
  --extra-instructions-file    Append extra operator-specific instructions
  -h, --help                   Show this help text
EOF
}

require_command() {
  local cmd="$1"
  if ! command -v "${cmd}" >/dev/null 2>&1; then
    printf 'missing required command: %s\n' "${cmd}" >&2
    exit 1
  fi
}

while [ "$#" -gt 0 ]; do
  case "$1" in
    --dispatch-json)
      dispatch_json="${2:-}"
      shift 2
      ;;
    --db)
      db_path="${2:-}"
      shift 2
      ;;
    --inbox-skill-path)
      inbox_skill_path="${2:-}"
      shift 2
      ;;
    --extra-instructions-file)
      extra_instructions_file="${2:-}"
      shift 2
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      printf 'unknown argument: %s\n' "$1" >&2
      usage >&2
      exit 1
      ;;
  esac
done

require_command jq

if [ -z "${dispatch_json}" ] || [ -z "${db_path}" ]; then
  usage >&2
  exit 1
fi

if [ ! -f "${dispatch_json}" ]; then
  printf 'dispatch json not found: %s\n' "${dispatch_json}" >&2
  exit 1
fi

if [ -n "${extra_instructions_file}" ] && [ ! -f "${extra_instructions_file}" ]; then
  printf 'extra instructions file not found: %s\n' "${extra_instructions_file}" >&2
  exit 1
fi

run_id="$(jq -r '.data.attempt.run_id // .data.task.run_id // empty' "${dispatch_json}")"
task_id="$(jq -r '.data.attempt.task_id // .data.task.task_id // empty' "${dispatch_json}")"
attempt_no="$(jq -r '.data.attempt.attempt_no // empty' "${dispatch_json}")"
assigned_to="$(jq -r '.data.attempt.assigned_to // .data.task.default_to // empty' "${dispatch_json}")"
thread_id="$(jq -r '.data.attempt.thread_id // .data.thread.thread_id // empty' "${dispatch_json}")"
worktree_path="$(jq -r '.data.attempt.worktree_path // empty' "${dispatch_json}")"
execution_mode="$(jq -r '.data.message.payload_json.execution_mode // empty' "${dispatch_json}")"
base_ref="$(jq -r '.data.attempt.base_ref // empty' "${dispatch_json}")"
task_title="$(jq -r '.data.task.title // empty' "${dispatch_json}")"
task_summary="$(jq -r '.data.task.summary // empty' "${dispatch_json}")"
leader_body="$(jq -r '.data.message.body // empty' "${dispatch_json}")"

if [ -z "${run_id}" ] || [ -z "${task_id}" ] || [ -z "${assigned_to}" ] || [ -z "${thread_id}" ]; then
  printf 'dispatch json is missing one or more required fields: run_id, task_id, assigned_to, thread_id\n' >&2
  exit 1
fi

if [ "${execution_mode}" != "analysis" ] && [ "${execution_mode}" != "code" ]; then
  printf 'dispatch json is missing a supported execution_mode in message.payload_json\n' >&2
  exit 1
fi
if [ "${execution_mode}" = "code" ] && [ -z "${worktree_path}" ]; then
  printf 'dispatch json is inconsistent: execution_mode=code requires a worktree_path\n' >&2
  exit 1
fi
if [ "${execution_mode}" = "analysis" ] && [ -n "${worktree_path}" ]; then
  printf 'dispatch json is inconsistent: execution_mode=analysis must not include a worktree_path\n' >&2
  exit 1
fi

cat <<EOF
Use \$inbox at ${inbox_skill_path} to act as ${assigned_to} on SQLite DB ${db_path}. Only coordinate through the bundled inbox CLI from the skill. Do not use ordinary chat to coordinate with the leader. Do not use orch.

You are assigned one existing attempt:
- run_id: ${run_id}
- task_id: ${task_id}
- attempt_no: ${attempt_no}
- assigned_to: ${assigned_to}
- thread_id: ${thread_id}
- execution_mode: ${execution_mode}
EOF

if [ -n "${task_title}" ]; then
  printf '%s\n' "- task_title: ${task_title}"
fi
if [ -n "${task_summary}" ]; then
  printf '%s\n' "- task_summary: ${task_summary}"
fi
if [ -n "${base_ref}" ]; then
  printf '%s\n' "- base_ref: ${base_ref}"
fi
if [ -n "${worktree_path}" ]; then
  printf '%s\n' "- worktree_path: ${worktree_path}"
fi

cat <<'EOF'

Required workflow:
1. Fetch or inspect the assigned thread and claim exactly the listed thread_id.
2. Inspect the thread with show before making assumptions about the task body or payload.
3. Send one in_progress update when real work starts.
4. If blocked, send one precise blocked question with update --status blocked and then use wait-reply.
5. Finish with done on success or fail on failure.
6. Stop after reporting the handled thread_id and a concise outcome summary.

Rules:
- Do not claim any other thread.
- Keep all coordination in inbox messages, not ordinary chat.
- Do not change the assigned_to, thread_id, or worktree assignment yourself.
EOF

if [ -n "${worktree_path}" ]; then
  cat <<EOF
- Perform repository work only inside ${worktree_path}.
- Do not modify the leader's primary checkout outside the assigned worktree.
EOF
fi

if [ -n "${leader_body}" ]; then
  printf '\nLeader dispatch body:\n%s\n' "${leader_body}"
fi

if [ -n "${extra_instructions_file}" ]; then
  printf '\nExtra instructions:\n'
  cat "${extra_instructions_file}"
  printf '\n'
fi
