# shellcheck shell=bash

_okstra_ctl_tail() {
  if [[ $# -lt 1 ]]; then
    printf 'tail: missing <runId-or-prefix> | active\n' >&2; exit 2
  fi
  if [[ "$1" == "active" ]]; then
    OKSTRA_HOME_RESOLVED="$(okstra_central_home)" \
    OKSTRA_CTL_LIB_DIR="$SCRIPT_DIR" \
    python3 - <<'PY'
import os, sys
sys.path.insert(0, os.environ["OKSTRA_CTL_LIB_DIR"])
from pathlib import Path
from okstra_ctl import read_run_index, format_runs_table
# tail active 는 active.jsonl 자체를 보여줘야 한다 — running 외에도
# in-progress(backfill), reserving(rerun 예약), 그리고 어떤 비-터미널
# 상태든 active 에 들어있는 것은 사용자가 모니터링해야 할 대상이다.
# 디스크 row 는 slim(파생 taskType 없음)이라 read_run_index 로 hydrate 해야
# format_runs_table 의 TASK-TYPE 열이 채워진다.
rows = sorted(read_run_index(Path(os.environ["OKSTRA_HOME_RESOLVED"]) / "active.jsonl"),
              key=lambda r: r.get("startedAt", ""), reverse=True)
print(format_runs_table(rows), end="")
PY
    return 0
  fi
  # 정확한 status 파일 경로는 row 의 finalStatusRel(RUN_STATUS_SEQ 기반,
  # record_start 시점에 박힘) 에서 가져온다. RUN_STATUS_SEQ 와
  # RUN_MANIFESTS_SEQ 는 별개 카운터이므로 row["runSeq"] 로 추정하면
  # render-only 가 manifest seq 만 advance 한 직후의 실행에서 어긋난다.
  # finalStatusRel 이 없을 때만 (구식 row) runDirRel/taskType/runSeq 로
  # fallback 하고, 그래도 없으면 expected status 파일이 아직 만들어지지
  # 않았어도 tail -F 로 wait 한다(`tail -F` 는 by-name 으로 파일 등장을
  # 감지한다).
  local resolved resolve_rc
  resolved="$(OKSTRA_HOME_RESOLVED="$(okstra_central_home)" \
              OKSTRA_CTL_LIB_DIR="$SCRIPT_DIR" \
              OK_QUERY="$1" python3 -c '
import os, sys
sys.path.insert(0, os.environ["OKSTRA_CTL_LIB_DIR"])
from pathlib import Path
from okstra_ctl import resolve_run_id, find_row_by_run_id, ResolveError, resolve_under_root
home = Path(os.environ["OKSTRA_HOME_RESOLVED"])
try:
    rid = resolve_run_id(home, os.environ["OK_QUERY"])
except ResolveError as e:
    print(f"tail: {e}", file=sys.stderr)
    for c in e.candidates: print(f"  - {c}", file=sys.stderr)
    sys.exit(2)
row = find_row_by_run_id(home, rid)
if row is None:
    print(f"tail: row not found for {rid}", file=sys.stderr); sys.exit(2)
project_root = Path(row["projectRoot"])
run_dir = resolve_under_root(project_root, row.get("runDirRel"))
if run_dir is None:
    print("tail: runDirRel escapes project root", file=sys.stderr); sys.exit(2)
status_rel = row.get("finalStatusRel") or ""
status_abs = str(project_root / status_rel) if status_rel else ""
print(run_dir)
print(row.get("taskType", ""))
print(int(row.get("runSeq", 0)))
print(status_abs)
')"
  resolve_rc=$?
  # resolve 단계가 ResolveError/누락 row 로 exit≠0 한 경우 stderr 의 깔끔한
  # `tail: ...` 메시지를 살리고 fallback glob 으로 넘어가지 않는다.
  if [[ $resolve_rc -ne 0 ]]; then exit "$resolve_rc"; fi
  local rid task_type seq status_abs
  rid="$(printf '%s\n' "$resolved" | sed -n '1p')"
  task_type="$(printf '%s\n' "$resolved" | sed -n '2p')"
  seq="$(printf '%s\n' "$resolved" | sed -n '3p')"
  status_abs="$(printf '%s\n' "$resolved" | sed -n '4p')"
  if [[ -n "$status_abs" ]]; then
    # row 가 정식 경로를 알고 있으면 그것만 tail. 아직 파일이 없어도
    # `tail -F` 가 등장을 기다리므로, active 진입 직후 호출도 정상.
    exec tail -F "$status_abs"
  fi
  # 구식 row(이전 버전에서 작성되어 finalStatusRel 누락) — runSeq 로 glob.
  if [[ ! -d "$rid/status" ]]; then
    printf 'tail: status dir missing: %s/status\n' "$rid" >&2; exit 2
  fi
  local seq_pad
  seq_pad="$(printf '%03d' "$seq")"
  shopt -s nullglob
  local matches=("$rid/status/"*"-${task_type}-${seq_pad}".*)
  shopt -u nullglob
  if [[ ${#matches[@]} -eq 0 ]]; then
    # 매니페스트 카운터가 status 카운터를 앞섰을 수 있으므로 정확
    # 매칭이 없어도 가장 그럴듯한 expected 경로로 wait 한다.
    exec tail -F "$rid/status/final-${task_type}-${seq_pad}.status"
  fi
  exec tail -F "${matches[@]}"
}
