#!/usr/bin/env python3
"""scripts/run_completion_callback_fallback_cancel.py

task-2553+9a — CALLBACK_FALLBACK_CANCEL_ON_SUCCESS CLI 호출 seam (§9-R.4).

본 CLI 가 메커니즘의 **단독 호출점**이다. 운영 normal-collector flow 는 자기
success marker(result.json/report/collector-result marker) 생성 **후** 이
CLI 를 1줄 호출한다(또는 collector dispatch prompt 의 마지막 step 에 CLI 호출
한 줄 추가 — dispatch prompt text 일 뿐 orchestrator 코드 아님).

  utils/anu_delegation_completion_callback.py 는 import/호출하지 않는다 —
  byte-identical 무수정. → §7 HOLD("collector 본체 수정 필요") 구조적 미발생.

입력:
  --dispatch-fired-marker  dispatch-fired marker 경로(§9-R.1 단일 권위)
  --task-id                현재 처리 task_id
  --target-cron-id         제거 대상(=marker 권위 id 와 정확 일치해야)
  --result-json/--report/--collector-result-marker  §9-R.2 durable evidence
  --normal-collector-success  보조 신호(bool) — §9-R.2 gate 에 종속, 단독 권위 아님
  --callback-contract      교차확인용 보조 contract json (선택)
  --out                    cancel-result JSON 출력 경로
  --dry-run / --no-dry-run 기본 dry-run(실 subprocess 0). 운영 collector 만 --no-dry-run
"""
from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path

WORKSPACE = Path(__file__).resolve().parent.parent
if str(WORKSPACE) not in sys.path:
    sys.path.insert(0, str(WORKSPACE))

from utils.completion_callback_fallback_cancel import (  # noqa: E402
    cancel_fallback_on_success,
)


def _load_contract(path: str | None) -> dict | None:
    if not path:
        return None
    try:
        return json.loads(Path(path).read_text(encoding="utf-8"))
    except (OSError, json.JSONDecodeError):
        return None


def build_parser() -> argparse.ArgumentParser:
    p = argparse.ArgumentParser(description="task-2553+9a fallback cancel-on-success")
    p.add_argument("--dispatch-fired-marker", required=True)
    p.add_argument("--task-id", required=True)
    p.add_argument("--target-cron-id", required=True)
    p.add_argument("--result-json", required=True)
    p.add_argument("--report", required=True)
    p.add_argument("--collector-result-marker", required=True)
    p.add_argument("--fallback-cancelled-marker", default=None)
    p.add_argument("--cancel-lock", default=None)
    p.add_argument("--callback-contract", default=None)
    p.add_argument(
        "--normal-collector-success",
        action="store_true",
        help="보조 신호 — §9-R.2 durable-evidence gate 에 종속, 단독 권위 아님",
    )
    p.add_argument("--out", required=True)
    p.add_argument(
        "--dry-run",
        dest="dry_run",
        action="store_true",
        default=True,
        help="기본값 — 실 subprocess --cron-remove 호출 0",
    )
    p.add_argument(
        "--no-dry-run",
        dest="dry_run",
        action="store_false",
        help="운영 collector 전용 — 실 cron 제거",
    )
    return p


def main(argv: list[str] | None = None) -> int:
    args = build_parser().parse_args(argv)
    decision = cancel_fallback_on_success(
        task_id=args.task_id,
        target_cron_id=args.target_cron_id,
        dispatch_fired_marker_path=Path(args.dispatch_fired_marker),
        result_json_path=Path(args.result_json),
        report_path=Path(args.report),
        collector_result_marker_path=Path(args.collector_result_marker),
        fallback_cancelled_marker_path=(
            Path(args.fallback_cancelled_marker)
            if args.fallback_cancelled_marker
            else None
        ),
        cancel_lock_path=Path(args.cancel_lock) if args.cancel_lock else None,
        callback_contract=_load_contract(args.callback_contract),
        normal_collector_success=args.normal_collector_success,
        dry_run=args.dry_run,
    )
    out_path = Path(args.out)
    out_path.parent.mkdir(parents=True, exist_ok=True)
    out_path.write_text(
        json.dumps(decision.to_dict(), ensure_ascii=False, indent=2),
        encoding="utf-8",
    )
    print(json.dumps(decision.to_dict(), ensure_ascii=False))
    # cancel skip/untrusted/normal-failed 는 정상 흐름(실패 아님) → exit 0.
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
