"""Consumer connector & widget boundary validation — Phase 11.9."""
from typing import Any

from app.validators.foundation import ValidationError
from shared.exceptions import AppError

FORBIDDEN_OWNERSHIP_KEYS = frozenset(
    {
        "sms_provider",
        "payamak",
        "provider_registry",
        "communication_engine",
        "provider_adapter",
        "message_queue",
        "dlq",
        "menu_catalog",
        "product_catalog",
        "crm_contact_id",
        "member_id",
        "booking_engine",
        "schedule_engine",
        "analytics_engine",
        "ai_content_engine",
        "model_inference",
        "plan_engine",
        "subscription_engine",
        "billing_ledger",
        "core_plan_id",
    }
)


def _reject_forbidden(value: dict, field: str) -> None:
    banned = FORBIDDEN_OWNERSHIP_KEYS.intersection(value.keys())
    if banned:
        raise ValidationError(
            "کلیدهای مالکیت سرویس‌های دیگر در payload مجاز نیست",
            {"field": field, "forbidden_keys": sorted(banned)},
        )


def validate_json_object(value: Any, field: str) -> dict | None:
    if value is None:
        return None
    if not isinstance(value, dict):
        raise ValidationError(f"{field} باید object باشد", {"field": field})
    _reject_forbidden(value, field)
    return value


def validate_metadata(value: Any) -> dict | None:
    return validate_json_object(value, "metadata_json")


def validate_config(value: Any) -> dict | None:
    return validate_json_object(value, "config_json")


def validate_default_config(value: Any) -> dict | None:
    return validate_json_object(value, "default_config_json")


def validate_payload(value: Any) -> dict | None:
    return validate_json_object(value, "payload_json")


def ensure_transition(current, target, transitions: dict, label: str) -> None:
    if current == target:
        return
    if target not in transitions.get(current, frozenset()):
        raise AppError(
            f"گذار وضعیت {label} مجاز نیست",
            error_code=f"invalid_{label}_status_transition",
            status_code=409,
            details={"current": current.value, "target": target.value},
        )
