#!/usr/bin/env bash
# next-bd: Show ready beads ranked by priority, with labels, filtered against blocked.
# Usage: next-bd [OPTIONS]
set -euo pipefail

usage() {
  cat <<'EOF'
Usage: next-bd [OPTIONS]

Options:
  --list         Include complete non-selectable in-progress, blocked, deferred tables
  --in-progress  Include a compact in-progress summary (ignored with --list)
  --avoid-busy   Exclude ready beads whose labels are busy in their store
  --json         Print ranked candidates as JSON
  --type=TYPE    Include only candidates of the given issue type
  --help         Show this help and exit
EOF
}

FULL_LIST=false
SHOW_IN_PROGRESS=false
AVOID_BUSY=false
JSON_OUTPUT=false
TYPE_FILTER=""
for arg in "$@"; do
  case "$arg" in
    --list)        FULL_LIST=true ;;
    --in-progress) SHOW_IN_PROGRESS=true ;;
    --avoid-busy)  AVOID_BUSY=true ;;
    --json)        JSON_OUTPUT=true ;;
    --type=*)      TYPE_FILTER=${arg#--type=} ;;
    --help)        usage; exit 0 ;;
  esac
done

SCRIPT_DIR=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd)
payload=$("$SCRIPT_DIR/collect.py")

if "$JSON_OUTPUT"; then
  jq -r '.diagnostics[] | "next-bd: \(.)"' <<< "$payload" >&2
fi

jq -r \
  --arg full_list "$FULL_LIST" \
  --arg show_ip "$SHOW_IN_PROGRESS" \
  --arg avoid_busy "$AVOID_BUSY" \
  --arg json_output "$JSON_OUTPUT" \
  --arg type_filter "$TYPE_FILTER" '
  def cell: (. // "—") | tostring | gsub("[\\r\\n]+"; " ") | gsub("\\|"; "&#124;");
  def row: "| " + (map(cell) | join(" | ")) + " |";
  def blocker_context:
    if (.blocked_by // [] | length) > 0 then .blocked_by | join(", ")
    elif (.blocked_by_count // 0) > 0 then "\(.blocked_by_count) blockers"
    else "—" end;
  def non_ready_table($title; $rows; $workspace; $extra):
    ((if $workspace then ["Repo"] else [] end) +
      ["ID", "Pri", "Type", "Labels", "Title"] +
      (if $extra == "" then [] else [$extra] end)) as $headers |
    "\n\n## \($title) (\($rows | length) beads; not selectable)\n" +
    (if $title == "In Progress" then "\nTracker claims; session activity unverified.\n" else "" end) +
    (if ($rows | length) == 0 then "\n_None._" else
      "\n" + ($headers | row) + "\n" + ($headers | map("---") | row) + "\n" +
      ($rows | sort_by(.priority, .created_at, (.repository // ""), .id) | map(
        ((if $workspace then [.repository] else [] end) +
          [.id, (if .priority == null then "—" else "P\(.priority)" end),
           .issue_type, (.labels // [] | if length == 0 then "-" else join(", ") end), .title] +
          (if $extra == "Blocked by" then [blocker_context]
           elif $extra == "Defer until" then [.defer_until]
           else [] end)) | row
      ) | join("\n"))
    end);

  . as $payload |
  ($payload.workspace) as $workspace |
  ($payload.blocked | map("\(.repository // "")\u0000\(.id)")) as $blocked_keys |
  ($payload.in_progress) as $in_progress |
  ($payload.diagnostics) as $diagnostics |

  ($payload.ready |
    map(select(.priority >= 0 and .priority <= 3)) |
    map(select(
      . as $candidate |
      "\($candidate.repository // "")\u0000\($candidate.id)" as $candidate_key |
      $blocked_keys | index($candidate_key) | not
    )) |
    if $type_filter != "" then
      map(select(.issue_type == $type_filter))
    else . end |
    if $avoid_busy == "true" then
      map(
        . as $candidate |
        ($in_progress |
          map(
            select((.repository // "") == ($candidate.repository // "")) |
            (.labels // [])
          ) |
          flatten |
          unique
        ) as $busy_labels |
        ($candidate.labels // []) as $labels |
        select(
          ($labels | length) == 0 or
          ([$labels[] | select(. as $label | $busy_labels | index($label) | not)] | length) ==
            ($labels | length)
        )
      )
    else . end |
    map(. + {
      rank: (
        if .priority == 0 then 1
        elif .priority == 1 and .issue_type == "bug" then 2
        elif .priority == 2 and .issue_type == "bug" then 3
        elif .priority == 1 and (.issue_type == "feature" or .issue_type == "task") then 4
        elif .priority == 1 and .issue_type == "epic" then 5
        elif .priority == 2 and (.issue_type == "feature" or .issue_type == "task") then 6
        elif .priority == 3 and (.issue_type == "bug" or .issue_type == "feature" or .issue_type == "task") then 7
        elif .priority == 2 and .issue_type == "epic" then 8
        elif .priority == 3 and .issue_type == "epic" then 9
        else 10
        end
      )
    }) |
    sort_by(.rank, .created_at, (.repository // ""), .id)
  ) as $ranked |

  if $json_output == "true" then
    $ranked
  else
    "## Ready to Work (\($ranked | length) beads)\n" +
    (if $workspace then
      "| # | Repo | ID | Pri | Type | Labels | Title |\n" +
      "|---|---|---|---|---|---|---|\n"
    else
      "| # | ID | Pri | Type | Labels | Title |\n" +
      "|---|---|---|---|---|---|\n"
    end) +
    ($ranked | to_entries | map(
      if $workspace then
        "| \(.key + 1) | \(.value.repository) | \(.value.id) | P\(.value.priority) | \(.value.issue_type) | \(.value.labels // [] | if length == 0 then "-" else join(", ") end) | \(.value.title) |"
      else
        "| \(.key + 1) | \(.value.id) | P\(.value.priority) | \(.value.issue_type) | \(.value.labels // [] | if length == 0 then "-" else join(", ") end) | \(.value.title) |"
      end
    ) | join("\n")) +
    if $full_list == "true" then
      non_ready_table("In Progress"; $in_progress; $workspace; "") +
      non_ready_table("Blocked"; $payload.blocked; $workspace; "Blocked by") +
      non_ready_table("Deferred"; $payload.deferred; $workspace; "Defer until")
    elif $show_ip == "true" and ($in_progress | length) > 0 then
      "\n\nTracker status: in progress (session activity unverified):\n" +
      ($in_progress | map(
        if $workspace then
          "- [\(.repository)] `\(.id)` (P\(.priority) \(.issue_type)) \"\(.title)\""
        else
          "- `\(.id)` (P\(.priority) \(.issue_type)) \"\(.title)\""
        end
      ) | join("\n"))
    else "" end +
    if ($diagnostics | length) > 0 then
      "\n\nSource diagnostics:\n" +
      ($diagnostics | map("- " + .) | join("\n"))
    else "" end
  end
' <<< "$payload"
