"""목적별 Okstra 소유 JSON에서 고정 Markdown 입력을 렌더한다.

구현은 `model_io/` 아래 세 층으로 나뉜다 — 참조 해석(`references`),
줄 서식(`lines`), 조립(`renderers`). 이 파일은 인자 표면만 갖는다.
"""
from __future__ import annotations

import argparse
import sys
from pathlib import Path

from .json_boundary import JsonBoundaryError
from .model_io.renderers import (
    render_active_context_input,
    render_code_review_input,
    render_error_zip_input,
    render_group_recap_input,
    render_history_input,
    render_project_context,
    render_recap_input,
    render_report_input,
    render_rerun_input,
    render_run_input,
    render_schedule_input,
    render_status_input,
    render_task_selection_input,
)


_CLI_EPILOG = r"""Usage:
  okstra model-io project-context --project-root <dir> [--task-ref <task-id|task-key|task-manifest-path>]
  okstra model-io run-input --run-manifest <path>
  okstra model-io active-context-input --project-root <dir> --run-manifest <path>
  okstra model-io schedule-input --project-root <dir> --task-group <id>
  okstra model-io code-review-input --project-root <dir> --base <ref> --head <ref>

Output: purpose-specific Markdown only. This command has no generic JSON path,
key lookup, or JSON-output option.
"""


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        epilog=_CLI_EPILOG,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        prog="okstra model-io",
        description="Render fixed Markdown views of Okstra-owned JSON.",
    )
    commands = parser.add_subparsers(dest="command", required=True)
    project = commands.add_parser("project-context")
    project.add_argument("--project-root", required=True)
    project.add_argument("--task-ref", default="")
    run = commands.add_parser("run-input")
    run.add_argument("--run-manifest", required=True)
    active = commands.add_parser("active-context-input")
    active.add_argument("--project-root", required=True)
    active.add_argument("--run-manifest", required=True)
    schedule = commands.add_parser("schedule-input")
    schedule.add_argument("--project-root", required=True)
    schedule.add_argument("--task-group", required=True)
    review = commands.add_parser("code-review-input")
    review.add_argument("--project-root", required=True)
    review.add_argument("--base", required=True)
    review.add_argument("--head", required=True)
    for name in ("status-input", "history-input", "report-input"):
        inspect = commands.add_parser(name)
        inspect.add_argument("--project-root", required=True)
        inspect.add_argument("--task-ref", required=name == "report-input", default="")
        if name != "report-input":
            inspect.add_argument("--task-type", default="")
            inspect.add_argument("--latest-run-status", default="")
            inspect.add_argument("--task-group", default="")
            if name == "history-input":
                inspect.add_argument("--limit", type=int, default=20)
    recap = commands.add_parser("recap-input")
    recap.add_argument("--project-root", required=True)
    recap_scope = recap.add_mutually_exclusive_group(required=True)
    recap_scope.add_argument("--task-ref", default="")
    recap_scope.add_argument("--task-group", default="")
    rerun = commands.add_parser("rerun-input")
    rerun.add_argument("--run-manifest", required=True)
    commands.add_parser("error-zip-input")
    selection = commands.add_parser("task-selection-input")
    selection.add_argument("--project-root", required=True)
    selection.add_argument("--task-ref", default="")
    return parser


def main(argv: list[str] | None = None) -> int:
    args = build_parser().parse_args(argv)
    try:
        if args.command == "project-context":
            text = render_project_context(Path(args.project_root), args.task_ref)
        elif args.command == "run-input":
            text = render_run_input(Path(args.run_manifest))
        elif args.command == "active-context-input":
            text = render_active_context_input(
                Path(args.project_root), Path(args.run_manifest)
            )
        elif args.command == "schedule-input":
            text = render_schedule_input(Path(args.project_root), args.task_group)
        elif args.command == "code-review-input":
            text = render_code_review_input(Path(args.project_root), args.base, args.head)
        elif args.command == "status-input":
            text = render_status_input(
                Path(args.project_root), args.task_ref,
                task_type=args.task_type,
                latest_run_status=args.latest_run_status,
                task_group=args.task_group,
            )
        elif args.command == "history-input":
            text = render_history_input(
                Path(args.project_root), args.task_ref,
                task_type=args.task_type,
                latest_run_status=args.latest_run_status,
                task_group=args.task_group,
                limit=max(0, args.limit),
            )
        elif args.command == "recap-input" and args.task_group:
            text = render_group_recap_input(Path(args.project_root), args.task_group)
        elif args.command == "recap-input":
            text = render_recap_input(Path(args.project_root), args.task_ref)
        elif args.command == "report-input":
            text = render_report_input(Path(args.project_root), args.task_ref)
        elif args.command == "rerun-input":
            text = render_rerun_input(Path(args.run_manifest))
        elif args.command == "error-zip-input":
            text = render_error_zip_input()
        elif args.command == "task-selection-input":
            text = render_task_selection_input(Path(args.project_root), args.task_ref)
        else:  # argparse가 도달 불가로 만들지만 명시적 종료 경계를 유지한다.
            raise ValueError(f"unsupported command: {args.command}")
    except JsonBoundaryError as exc:
        print(f"model-io: {exc}", file=sys.stderr)
        return 2
    print(text, end="")
    return 0


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