#!/bin/bash
#
# channels-multi-repo.sh
# Multi-repo dispatch adapter for `/multi-agent:channels`. Reads agent-state.json
# `projects[]` array, derives cross-linked PR URL set, and emits per-target
# bodies for the channels.md Step 6 fan-out.
#
# Subcommands:
#   targets     <state.json>                  Emit JSON array [{repoName, prUrl, isPrimary, crossLinks}] for the dispatcher loop.
#   render-pr   <state.json> <body.md> <repo> Emit the per-PR body with cross-links substituted (stdout).
#   render-jira <state.json> <body.md>        Emit the Jira comment with all PR URLs as a bulleted list (stdout).
#   render-conf <state.json> <body.md>        Emit the Confluence body with `Related PRs` block prepended (stdout).
#   summary     <state.json>                  Human-readable line: "1 primary + N extras: [pr-urls]"  -  for autopilot logs.
#
# Single-repo tasks: every subcommand falls through to the single PR / single
# body  -  `targets` returns one entry, render-* leaves the body unchanged.

set -euo pipefail

CMD="${1:-}"
STATE="${2:-}"

[ -z "$CMD" ] || [ -z "$STATE" ] && {
  echo "usage: $0 {targets|render-pr|render-jira|render-conf|summary} <state.json> [args]" >&2
  exit 1
}
[ ! -f "$STATE" ] && { echo "ERR: state file not found: $STATE" >&2; exit 2; }

# count_matches: single-line numeric grep -c (the bare `grep -c || echo 0`
# idiom emits "0" twice on zero matches and breaks the -le comparisons below).
# shellcheck source=count-lib.sh disable=SC1091
. "$(cd "$(dirname "$0")" && pwd)/count-lib.sh"

# --- Helpers ----------------------------------------------------------------
# Extract the targets array from agent-state.json. Output: TSV with columns
# repoName, prUrl, isPrimary (1/0). One target per row.
extract_targets() {
  python3 - "$STATE" <<'PY'
import json, sys
state = json.load(open(sys.argv[1]))
projects = state.get("projects") or []
if not projects:
    # single-repo state  -  synthesize one target from top-level fields
    pr = state.get("pr") or {}
    pr_url = pr.get("url") or ""
    name = state.get("project") or "primary"
    print(f"{name}\t{pr_url}\t1")
    sys.exit(0)
primary_name = state.get("project") or projects[0].get("project")
for p in projects:
    name = p.get("project") or ""
    pr = p.get("pr") or {}
    pr_url = pr.get("url") or ""
    is_primary = "1" if name == primary_name else "0"
    print(f"{name}\t{pr_url}\t{is_primary}")
PY
}

# Collect every PR URL into a single space-separated list (primary first).
all_pr_urls() {
  extract_targets | awk -F'\t' '
    $3=="1" { primary=$2 }
    $3=="0" { extras=extras " " $2 }
    END { if (primary) printf "%s", primary; printf "%s\n", extras }
  '
}

# --- targets subcommand -----------------------------------------------------
do_targets() {
  python3 - "$STATE" <<'PY'
import json, sys
state = json.load(open(sys.argv[1]))
projects = state.get("projects") or []
if not projects:
    pr = state.get("pr") or {}
    out = [{
        "repoName": state.get("project") or "primary",
        "prUrl":    pr.get("url") or "",
        "prNumber": pr.get("number"),
        "isPrimary": True,
        "crossLinks": [],
    }]
    print(json.dumps(out))
    sys.exit(0)

primary_name = state.get("project") or projects[0].get("project")
all_urls = []
for p in projects:
    pr = p.get("pr") or {}
    if pr.get("url"):
        all_urls.append({"repo": p.get("project") or "", "url": pr["url"]})

out = []
for p in projects:
    name = p.get("project") or ""
    pr = p.get("pr") or {}
    is_primary = (name == primary_name)
    cross = [u for u in all_urls if u["repo"] != name]
    out.append({
        "repoName": name,
        "prUrl":    pr.get("url") or "",
        "prNumber": pr.get("number"),
        "isPrimary": is_primary,
        "crossLinks": cross,
    })
print(json.dumps(out))
PY
}

# --- render-pr subcommand ---------------------------------------------------
# Args: state.json body.md repoName
# Inserts the cross-link block at the top of the body for the named target.
do_render_pr() {
  local body_file="${3:-}" repo="${4:-}"
  [ -z "$body_file" ] || [ -z "$repo" ] && {
    echo "usage: $0 render-pr <state.json> <body.md> <repoName>" >&2
    exit 3
  }
  [ ! -f "$body_file" ] && { echo "ERR: body file not found: $body_file" >&2; exit 2; }

  python3 - "$STATE" "$body_file" "$repo" <<'PY'
import json, sys
state = json.load(open(sys.argv[1]))
body = open(sys.argv[2]).read()
repo = sys.argv[3]

projects = state.get("projects") or []
if len(projects) <= 1:
    # Single-repo: pass through unchanged
    sys.stdout.write(body)
    sys.exit(0)

primary_name = state.get("project") or projects[0].get("project")
is_primary = (repo == primary_name)
links = []
for p in projects:
    if (p.get("project") or "") == repo:
        continue
    pr = p.get("pr") or {}
    if pr.get("url"):
        label = "Part of" if not is_primary and (p.get("project") or "") == primary_name else "Related"
        links.append(f"{label}: {pr['url']}")

if not links:
    sys.stdout.write(body)
    sys.exit(0)

prefix = "\n".join(links) + "\n\n"
sys.stdout.write(prefix + body)
PY
}

# --- render-jira subcommand -------------------------------------------------
# Single Jira comment for all repos. Replaces the "first line PR URL" with a
# bulleted list of every PR URL, primary first.
do_render_jira() {
  local body_file="${3:-}"
  [ -z "$body_file" ] && { echo "usage: $0 render-jira <state.json> <body.md>" >&2; exit 3; }
  [ ! -f "$body_file" ] && { echo "ERR: body file not found: $body_file" >&2; exit 2; }

  local urls
  urls=$(all_pr_urls | tr ' ' '\n' | grep -v '^$' || true)
  local count
  count=$(printf '%s\n' "$urls" | count_matches .)

  if [ "$count" -le 1 ]; then
    cat "$body_file"
    return
  fi

  # Multi-repo: prepend a `* PR: <url>` block for each (Jira wiki markup).
  printf '%s\n' "$urls" | sed 's/^/* PR: /'
  printf '\n'
  cat "$body_file"
}

# --- render-conf subcommand -------------------------------------------------
# Single Confluence page for all repos. Prepend a `Related PRs` heading block.
do_render_conf() {
  local body_file="${3:-}"
  [ -z "$body_file" ] && { echo "usage: $0 render-conf <state.json> <body.md>" >&2; exit 3; }
  [ ! -f "$body_file" ] && { echo "ERR: body file not found: $body_file" >&2; exit 2; }

  local urls
  urls=$(all_pr_urls | tr ' ' '\n' | grep -v '^$' || true)
  local count
  count=$(printf '%s\n' "$urls" | count_matches .)

  if [ "$count" -le 1 ]; then
    cat "$body_file"
    return
  fi

  printf '## Related PRs\n\n'
  printf '%s\n' "$urls" | sed 's/^/- /'
  printf '\n---\n\n'
  cat "$body_file"
}

# --- summary subcommand -----------------------------------------------------
do_summary() {
  python3 - "$STATE" <<'PY'
import json, sys
state = json.load(open(sys.argv[1]))
projects = state.get("projects") or []
if len(projects) <= 1:
    print("single-repo task")
    sys.exit(0)
primary_name = state.get("project") or projects[0].get("project")
extras = [p for p in projects if (p.get("project") or "") != primary_name]
extra_urls = [(p.get("pr") or {}).get("url") or f"<no-pr:{p['project']}>" for p in extras]
print(f"1 primary ({primary_name}) + {len(extras)} extras: {' '.join(extra_urls)}")
PY
}

case "$CMD" in
  targets)     do_targets ;;
  render-pr)   do_render_pr "$@" ;;
  render-jira) do_render_jira "$@" ;;
  render-conf) do_render_conf "$@" ;;
  summary)     do_summary ;;
  *) echo "ERR: unknown subcommand $CMD" >&2; exit 1 ;;
esac
