"""
promotion_guard.py — ANU v2.13 promotion transition guard (순수 함수, stdlib only)

APPROVED 전환은 chair / independent_verifier / anu-control 만 가능.
bot token 등 비승인 actor 의 APPROVED 전환 시도 → PROMOTION_SELF_APPROVAL_BLOCKED.
코드는 검사만 수행하며 DB 접근 / APPROVED 부여 0건.
"""

# ---------------------------------------------------------------------------
# 승인 권한 actors
# ---------------------------------------------------------------------------

APPROVER_ACTORS = frozenset([
    "chair",
    "independent_verifier",
    "anu-control",
    "anu_control",
])

# actor 매칭은 소문자 비교 — 매 호출마다 set 을 재생성하지 않도록 1회 사전계산.
_APPROVER_ACTORS_LOWER = frozenset(a.lower() for a in APPROVER_ACTORS)

# ---------------------------------------------------------------------------
# check_promotion_transition
# ---------------------------------------------------------------------------

def check_promotion_transition(actor, frm, to):
    """
    Parameters
    ----------
    actor : str  — 전환을 시도하는 actor
    frm : str    — 전환 전 상태 (예: "CANDIDATE")
    to : str     — 전환 후 상태 (예: "APPROVED")

    Returns
    -------
    dict {"blocked": bool, "verdict": str | None, "reason": str}
    """
    # actor/to/frm 가 non-string(int 등)이면 (x or "") 가 그대로 반환되어 .strip()
    # 에서 AttributeError. str() 로 감싸 type guard (MEDIUM).
    actor_lower  = str(actor or "").strip().lower()
    to_norm      = str(to  or "").strip().upper()
    frm_norm     = str(frm or "").strip().upper()

    if to_norm == "APPROVED":
        if actor_lower not in _APPROVER_ACTORS_LOWER:
            return {
                "blocked": True,
                "verdict": "PROMOTION_SELF_APPROVAL_BLOCKED",
                "reason":  (
                    f"actor={actor!r} is not an approved approver; "
                    f"transition {frm_norm!r} → {to_norm!r} blocked"
                ),
            }
        # Chair-class actor → 허용
        return {
            "blocked": False,
            "verdict": None,
            "reason":  (
                f"actor={actor!r} is a chair-class approver; "
                f"transition {frm_norm!r} → {to_norm!r} permitted"
            ),
        }

    # CANDIDATE / REJECTED / EXPIRED 전환 → 허용 (bot candidate 작성 / ANU-Control reject 허용)
    if to_norm in ("CANDIDATE", "REJECTED", "EXPIRED"):
        return {
            "blocked": False,
            "verdict": None,
            "reason":  (
                f"transition {frm_norm!r} → {to_norm!r} is permitted without chair approval"
            ),
        }

    # 그 외 미지정 상태 → 일단 허용 (unknown 상태는 gate에서 처리)
    return {
        "blocked": False,
        "verdict": None,
        "reason":  (
            f"transition {frm_norm!r} → {to_norm!r} is not a restricted transition"
        ),
    }
