"""Scalar parsing helpers for stage 020 contract metadata.

WHY:
    Mirrors stage 010's scalars module: small, dependency-free helpers that
    pull required/optional scalar fields out of a parsed TOML table and raise
    a clear ValueError on shape problems.

OBS:
    These helpers raise ValueError; the calling op catches and converts the
    failure into a CONTRACT_INVALID diagnostic. The helpers themselves stay
    Layer 0 and know nothing about diagnostics, files, schema policy, or
    canonical version authority.
"""

from accountable_record.boundary.toml import is_table


def required_string(table: dict[str, object], key: str, context: str) -> str:
    """Return a required non-empty string field from a table."""
    value = table.get(key)
    if not isinstance(value, str) or not value.strip():
        msg = f"{context} requires non-empty string field {key!r}"
        raise ValueError(msg)
    return value.strip()


def optional_string(table: dict[str, object], key: str) -> str | None:
    """Return an optional non-empty string field, or None."""
    value = table.get(key)
    if value is None:
        return None
    if not isinstance(value, str):
        msg = f"Expected string field {key!r}"
        raise ValueError(msg)

    stripped = value.strip()
    return stripped or None


def required_table(
    parent: dict[str, object], key: str, context: str
) -> dict[str, object]:
    """Return a required sub-table from a parent table."""
    value = parent.get(key)
    if not is_table(value):
        msg = f"{context} requires a [{key}] table"
        raise ValueError(msg)
    return value


def optional_bool(table: dict[str, object], key: str) -> bool | None:
    """Return an optional boolean field, or None."""
    value = table.get(key)
    if value is None:
        return None
    if not isinstance(value, bool):
        msg = f"Expected boolean field {key!r}"
        raise ValueError(msg)
    return value


def optional_table(parent: dict[str, object], key: str) -> dict[str, object] | None:
    """Return an optional sub-table, or None."""
    value = parent.get(key)
    if value is None:
        return None
    if not is_table(value):
        msg = f"Expected [{key}] to be a table"
        raise ValueError(msg)
    return value
