"""Small cross-cutting helpers shared across modules (kept dependency-light on purpose)."""
import re
from datetime import date, datetime, timezone


def iso(dt: date | None) -> str | None:
    """Serialize a date/datetime for a JSON response: ISO-8601, or None when the column is
    NULL. Single source of truth for the `x.isoformat() if x else None` idiom the routes had
    hand-rolled ~17 times — so a future tz/format tweak lands in one place. Accepts `date`
    too (datetime is a subclass) — e.g. MediaAsset.upload_date is a plain `date`."""
    return dt.isoformat() if dt is not None else None

# Single source of truth for "looks like an email" — used by every endpoint that accepts an
# address (auth register/reset/demo, admin invites + demo whitelist, the setup wizard). Keep
# the strictness in one place so routes don't drift between this and a looser "@"-in check.
_EMAIL_RE = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$")


def valid_email(value: str | None) -> bool:
    return bool(value and _EMAIL_RE.match(value))


def now_utc() -> datetime:
    """Current time as a timezone-aware UTC datetime."""
    return datetime.now(timezone.utc)
