"""dispatch.prompt — task-2386 슬림 prompt facade (task-2388 Phase ε).

dispatch 패키지의 본체는 `dispatch/__init__.py`에 있다.
이 facade는 build_prompt + resume + project_map 영역의 함수만 노출한다.

★ task-2386 슬림 prompt 개선판 보존 — 본체 코드는 무변경.

★ task-2640 (회장 verbatim unfork #3) — prompt 생성 전 ``enforce_callback_owner``
+ ``validate_spawn_callback_contract`` guard 통과를 확인. prompt 텍스트만으로
callback 정책 전달되는 구조 차단. 신규 ``build_prompt_with_contract`` 가
build_prompt 를 감싸고 PASS 시에만 prompt 본문을 반환한다.
"""

from __future__ import annotations

from typing import Optional, Sequence

from dispatch import _inject_project_map_context, _resolve_resume, build_prompt
from dispatch.callback_owner_enforcer import (
    ANU_KEY_2553,
    COLLECTOR_ROLE_ANU,
    DEFAULT_ANU_KEYS,
    PASS,
    enforce_callback_owner,
)
from dispatch.spawn_callback_contract_validator import (
    NO_OP_SPAWN_CONTRACT_FAILED,
    validate_spawn_callback_contract,
)


def build_prompt_with_contract(
    team_id: str,
    task_desc: str,
    task_id: str,
    level: str = "normal",
    project_id: Optional[str] = None,
    chain_id: Optional[str] = None,
    task_type: str = "coding",
    *,
    executor_key: str,
    anu_key: str = ANU_KEY_2553,
    dispatch_cron_id: str = "spawn-contract-precheck",
    normal_collector_cron_id: Optional[str] = "spawn-contract-precheck-normal",
    fallback_callback_cron_id: Optional[str] = None,
    no_fallback: bool = True,
    anu_keys: Optional[Sequence[str]] = None,
    chat_id: str = "",
) -> dict:
    """prompt 생성 전 callback contract 정합성 enforce guard 적용.

    Two-stage gate (텍스트+코드 이중 안전, task md ANCHOR-4):
      1. ``enforce_callback_owner`` — owner 4-tuple 검증 (collector_role=ANU,
         owner != executor, owner is independent ANU key).
      2. ``validate_spawn_callback_contract`` — 산출 prompt 본문이 anu_key
         텍스트 + collector_role + SELF_COLLECTOR/SENDFILE_ONLY/NOT_REGISTERED
         doctrine 토큰을 포함하는지 단언.

    enforce guard 가 PASS 일 때만 실제 build_prompt 호출 결과를 반환한다.
    FAIL 시 ``status: blocked`` + ``no_op_reason`` 반환 → 호출자는 spawn 진입
    자체를 차단해야 함.

    Returns:
        dict — {
            "status": "ok" | "blocked",
            "prompt": str | None,
            "enforce_verdict": str,
            "contract_verdict": str,
            "classifications": [..],
            "reasons": [..],
            "no_op_reason": NO_OP_SPAWN_CONTRACT_FAILED (blocked only),
        }
    """
    keys = tuple(anu_keys) if anu_keys is not None else tuple(DEFAULT_ANU_KEYS)

    # Stage 1: pre-build callback owner enforcement.
    enforce_result = enforce_callback_owner(
        task_id=task_id,
        executor_key=executor_key,
        collector_key=anu_key,
        collector_owner_key=anu_key,
        collector_role=COLLECTOR_ROLE_ANU,
        normal_collector_cron_id=normal_collector_cron_id,
        fallback_callback_cron_id=fallback_callback_cron_id,
        dispatch_cron_id=dispatch_cron_id,
        chat_id=chat_id,
        prompt_claims_anu_collector=True,
        entry_path="dispatch.core.main",
        anu_keys=keys,
        no_fallback=no_fallback,
    )
    if enforce_result.verdict != PASS:
        return {
            "status": "blocked",
            "prompt": None,
            "enforce_verdict": enforce_result.verdict,
            "contract_verdict": None,
            "classifications": list(enforce_result.classifications),
            "reasons": list(enforce_result.reasons),
            "no_op_reason": NO_OP_SPAWN_CONTRACT_FAILED,
            "schema": enforce_result.schema,
            "task_id": task_id,
        }

    # Stage 2: build prompt then validate doctrine injection.
    prompt = build_prompt(
        team_id=team_id,
        task_desc=task_desc,
        task_id=task_id,
        level=level,
        project_id=project_id,
        chain_id=chain_id,
        task_type=task_type,
    )

    contract_result = validate_spawn_callback_contract(
        task_id=task_id,
        executor_key=executor_key,
        anu_key=anu_key,
        prompt_text=prompt,
        anu_keys=keys,
    )
    if contract_result.verdict != PASS:
        return {
            "status": "blocked",
            "prompt": prompt,
            "enforce_verdict": enforce_result.verdict,
            "contract_verdict": contract_result.verdict,
            "classifications": list(contract_result.classifications),
            "reasons": list(contract_result.reasons),
            "no_op_reason": NO_OP_SPAWN_CONTRACT_FAILED,
            "schema": contract_result.schema,
            "task_id": task_id,
        }

    return {
        "status": "ok",
        "prompt": prompt,
        "enforce_verdict": enforce_result.verdict,
        "contract_verdict": contract_result.verdict,
        "classifications": [],
        "reasons": [
            "build_prompt_with_contract PASS — enforce_callback_owner + "
            "validate_spawn_callback_contract 양단 통과 (텍스트+코드 이중 안전)."
        ],
        "schema": contract_result.schema,
        "task_id": task_id,
    }


__all__ = [
    "_inject_project_map_context",
    "_resolve_resume",
    "build_prompt",
    # task-2640 prompt-time enforce guard (회장 verbatim unfork #3)
    "build_prompt_with_contract",
]
