"""dispatch.core — dispatch + cancel + main + composite + PRD facade (task-2388 Phase ε).

dispatch 패키지의 본체는 `dispatch/__init__.py`에 있다.
이 facade는 메인 dispatch 흐름 영역의 함수만 노출한다.

영역:
- chain / cleanup
- composite dispatch
- PRD parsing
- 메인 dispatch + retry
- cancel / main entry point

본체 코드 무변경.

★ task-2640 (회장 verbatim unfork #2) — 봇 spawn 직전 callback contract validator
결선 추가. 새 함수 ``dispatch_to_bot_with_contract`` 가 spawn 진입점이며,
``validate_spawn_callback_contract`` 를 호출해 ANU-owned callback contract
정합성을 fail-closed 검증한다. 실패 시 cokacdir --cron 발사 0 + 분류 반환.
"""

from __future__ import annotations

from typing import Optional, Sequence

from dispatch import (
    _cleanup_task,
    _dispatch_composite,
    _parse_prd_claude,
    _parse_prd_regex,
    _retry_with_fallback_key,
    _update_chain_task,
    cancel_task,
    dispatch,
    handle_prd,
    main,
)
from dispatch.callback_owner_enforcer import (
    ANU_KEY_2553,
    DEFAULT_ANU_KEYS,
    FAIL,
    HOLD,
    PASS,
)
from dispatch.spawn_callback_contract_validator import (
    NO_OP_SPAWN_CONTRACT_FAILED,
    ContractValidationResult,
    validate_spawn_callback_contract,
)


def dispatch_to_bot_with_contract(
    *,
    task_id: str,
    executor_key: str,
    prompt: str,
    anu_key: str = ANU_KEY_2553,
    anu_keys: Optional[Sequence[str]] = None,
    anu_keys_resolvable: bool = True,
) -> dict:
    """봇 spawn 직전 callback contract validator gate (회장 verbatim unfork #2).

    ANU-owned callback contract 부재 시 fail-closed (NO_OP_SPAWN_CONTRACT_FAILED).
    실제 ``subprocess.run("cokacdir", "--cron", ...)`` 호출은 본 함수가 PASS 를
    반환한 후에만 호출자(dispatch.dispatch / 외부 entrypoint)가 수행한다.

    Layer A / NO-CRON: 본 함수는 subprocess / cokacdir / merge / cron 0 호출.

    Args:
        task_id: spawn 대상 task id
        executor_key: spawn 대상 봇의 self key
        prompt: build_prompt 산출 본문 (텍스트 + 코드 contract 정합 검증)
        anu_key: independent ANU collector key (기본값 ``ANU_KEY_2553``)
        anu_keys: override 허용 ANU key 집합
        anu_keys_resolvable: ANU key 집합 resolution 가능 여부

    Returns:
        dict — {
            "status": "ok" | "blocked",
            "verdict": PASS|FAIL|HOLD_FOR_CHAIR,
            "classification": str | None,
            "classifications": [..],
            "reasons": [..],
            "schema": str,
            "task_id": str,
            "executor_key": str,
            "anu_key": str,
            "no_op_reason": NO_OP_SPAWN_CONTRACT_FAILED (FAIL only),
        }
    """
    keys = tuple(anu_keys) if anu_keys is not None else tuple(DEFAULT_ANU_KEYS)
    result: ContractValidationResult = validate_spawn_callback_contract(
        task_id=task_id,
        executor_key=executor_key,
        anu_key=anu_key,
        prompt_text=prompt,
        anu_keys=keys,
        anu_keys_resolvable=anu_keys_resolvable,
    )
    payload = result.to_json()
    if result.verdict == PASS:
        return {
            "status": "ok",
            **payload,
        }
    # FAIL / HOLD 모두 fail-closed — spawn 진입 차단.
    return {
        "status": "blocked",
        "no_op_reason": NO_OP_SPAWN_CONTRACT_FAILED,
        **payload,
    }


__all__ = [
    "_cleanup_task",
    "_dispatch_composite",
    "_parse_prd_claude",
    "_parse_prd_regex",
    "_retry_with_fallback_key",
    "_update_chain_task",
    "cancel_task",
    "dispatch",
    "handle_prd",
    "main",
    # task-2640 spawn-time contract gate (회장 verbatim unfork #2)
    "dispatch_to_bot_with_contract",
    "NO_OP_SPAWN_CONTRACT_FAILED",
    "ContractValidationResult",
    "validate_spawn_callback_contract",
    "FAIL",
    "HOLD",
    "PASS",
]
