"""진행 중 run 조회 — pane 회수 의무를 어느 run 에 걸지 고르는 데 쓴다.

호출자는 `SessionStart(compact)` 훅(`okstra-compact-reminder.sh`) 하나다. 압축
직후 리드에게 "이 run 의 끝난 워커 pane 을 라운드 경계마다 회수하라"는 의무를
재주입할 때, 그 대상이 되는 이 프로젝트의 진행 중 run 을 여기서 찾는다.

정본은 run 디렉터리다(ADR-0011). 신호는 그 run 의 가장 최근 team-state 에
비종결 배치가 남아 있는지다. 이전 구현은 `~/.okstra/active.jsonl` 을 읽었는데,
그 원장은 `initial_status="running"` 으로 기록된 run 만 담고 in-session 경로는
`--render-only` 강제로 항상 `prepared` 가 되어 종결로 라우팅된다 — 실측에서 그
파일은 0행이었고 이 훅은 한 번도 발화하지 않았다. `state/lead-pane.id` 도 신호가
못 된다: 한 번 기록된 뒤 지워지지 않아 끝난 run 을 영구히 진행 중으로 읽는다.
"""
from __future__ import annotations

import json
import sys
from pathlib import Path

from .dispatch_state import NON_TERMINAL_WORKER_STATUSES
from .json_boundary import JsonBoundaryError, load_owned_object


def _newest_team_state(state_dir: Path) -> Path | None:
    """한 run 디렉터리의 최신 team-state.

    seq 는 3자리 zero-pad 라 이름 정렬이 곧 순서다. run 하나에 seq 가 누적되고
    이전 라운드의 `in-progress` 행이 그 파일에 남으므로, 최신이 아닌 파일을 읽으면
    몇 시간 전에 끝난 run 을 진행 중으로 보고한다.
    """
    files = sorted(state_dir.glob("team-state-*.json"))
    return files[-1] if files else None


def _has_live_dispatch(team_state_path: Path) -> bool:
    try:
        payload = load_owned_object(team_state_path, artifact="team state")
    except JsonBoundaryError:
        return False
    if not isinstance(payload, dict):
        return False
    return any(
        isinstance(record, dict)
        and record.get("status") in NON_TERMINAL_WORKER_STATUSES
        for record in payload.get("workerDispatches", [])
    )


def in_flight_run_dirs(project_root: Path) -> list[Path]:
    """비종결 배치를 아직 들고 있는 이 프로젝트의 run 디렉터리 목록.

    `runs/<task-type>/` 와 stage 격리 run 의 `runs/<task-type>/stage-<N>/` 을 모두
    훑는다. 후자를 빼면 `implementation` 과 단일 stage `final-verification` 이
    통째로 누락된다.
    """
    tasks_root = Path(project_root) / ".okstra" / "tasks"
    if not tasks_root.is_dir():
        return []
    out: list[Path] = []
    for state_dir in sorted(tasks_root.glob("*/*/runs/**/state")):
        if not state_dir.is_dir():
            continue
        newest = _newest_team_state(state_dir)
        if newest is not None and _has_live_dispatch(newest):
            out.append(state_dir.parent)
    return out


def main(argv: list[str]) -> int:
    if len(argv) == 2 and argv[0] == "--in-flight-run-dirs-for":
        for run_dir in in_flight_run_dirs(Path(argv[1])):
            print(run_dir)
        return 0
    return 1


if __name__ == "__main__":
    raise SystemExit(main(sys.argv[1:]))
