"""Core-owned data-access limits. Callers pass the stored policy through unchanged."""

from __future__ import annotations

from src.domain.adopt.contract import AdoptionError, DataAccess

_IDENTIFIER_FIELDS = frozenset({"id", "external_id"})


def enforce_data_access(
    policy: DataAccess,
    *,
    method: str,
    allowlist_methods: set[str],
    fields: list[str] | None = None,
    forward_identity: bool = False,
) -> None:
    """Intersect the request with the stored policy. This does not widen it."""
    allowed = {item.upper() for item in policy.methods} & {item.upper() for item in allowlist_methods}
    if method.upper() not in allowed:
        raise AdoptionError("method_not_allowed", "method is outside the confirmed data-access intersection")
    copied = list(fields or [])
    if policy.copy_into_cloud == "none" and copied:
        raise AdoptionError("copy_denied", "copy_into_cloud is none")
    if policy.copy_into_cloud == "identifiers_only" and any(field not in _IDENTIFIER_FIELDS for field in copied):
        raise AdoptionError("copy_denied", "only identifiers may be copied")
    if policy.copy_into_cloud == "declared_fields" and any(field not in set(policy.declared_fields) for field in copied):
        raise AdoptionError("copy_denied", "field is outside the declared copy set")
    if forward_identity and not policy.forward_user_identity:
        raise AdoptionError("identity_forward_denied", "the bridged user id stays on the customer session")
