"""implementation-planning run-root 해소 규칙의 단일 참조점.

`plan_run_root` 는 한 planning run 의 산출물 루트다. consumers.jsonl(stage 완료
원장) 과 approved-plan(final-report) 이 모두 이 루트 기준으로 놓인다.

두 진입점이 같은 layout 규칙을 공유한다:
- final-verification 은 사용자가 넘긴 approved-plan 정본 경로에서 역산한다
  (``<plan_run_root>/reports/final-report-....data.json`` → ``parents[1]``).
- container 는 approved-plan 입력이 없으므로 task-key 로 planning run 디렉터리를
  스캔해 latest done run 을 고른다.
"""
from __future__ import annotations

import re
from pathlib import Path
from typing import NamedTuple

from .stage_targets import PrepareError

_FINAL_REPORT_RE = re.compile(
    r"final-report-implementation-planning-(\d+)\.data\.json$"
)


class PlanRun(NamedTuple):
    """task-key 로 역추적한 planning run: 산출물 루트 + approved-plan(final-report) 경로."""
    run_root: Path
    approved_plan_path: str


def list_implementation_planning_reports(reports_dir: Path) -> list[Path]:
    """Return numbered implementation-planning reports in latest-first order."""
    numbered: list[tuple[int, Path]] = []
    for report in reports_dir.glob(
        "final-report-implementation-planning-*.data.json"
    ):
        match = _FINAL_REPORT_RE.fullmatch(report.name)
        if match:
            numbered.append((int(match.group(1)), report))
    numbered.sort(key=lambda item: item[0], reverse=True)
    return [report for _, report in numbered]


def plan_run_root_from_approved_plan(approved_plan_path: str | Path) -> Path:
    """approved-plan(final-report) 경로에서 plan_run_root 를 역산한다.

    정본은 ``<plan_run_root>/reports/final-report-....data.json`` 에 놓이므로
    ``parents[1]`` 이 run-root 다. run.py(final-verification) 와 container 가
    이 한 규칙을 공유한다."""
    return Path(approved_plan_path).resolve().parents[1]


def resolve_plan_run_root_by_task_key(
    *, project_root: Path, task_group: str, task_id: str,
) -> PlanRun:
    """task-key 로 implementation-planning run 을 역추적한다.

    container 는 approved-plan 입력이 없어 디스크에서 planning run 을 찾아야 한다.
    ``<task_dir>/runs/implementation-planning/reports/`` 의 final-report 들을
    스캔해 done consumers 를 가진 run 중 seq 가 가장 큰(latest) run 의 run-root 와
    그 final-report 경로를 돌려준다. done run 이 없거나 모호하면 PrepareError.
    """
    from . import paths
    from .consumers import read_consumers

    reports_dir = paths.RunRef(
        project_root=project_root, task_group=task_group, task_id=task_id,
        task_type="implementation-planning",
    ).reports_dir
    if not reports_dir.is_dir():
        raise PrepareError(
            "container up: implementation-planning run 을 찾을 수 없습니다 "
            f"({reports_dir} 없음). 먼저 implementation-planning 을 완료하거나 "
            "approved-plan 경로를 직접 지정하세요."
        )
    candidates: list[tuple[Path, Path]] = []
    for report in list_implementation_planning_reports(reports_dir):
        run_root = plan_run_root_from_approved_plan(report)
        done = [r for r in read_consumers(run_root) if r.get("status") == "done"]
        if done:
            candidates.append((run_root, report))
    if not candidates:
        raise PrepareError(
            "container up: done 상태의 implementation-planning run 이 없습니다. "
            "stage 를 완료(implementation done)한 뒤 다시 시도하거나 approved-plan "
            "경로를 직접 지정하세요."
        )
    run_root, report = candidates[0]
    return PlanRun(run_root=run_root, approved_plan_path=str(report))
