"""Artifact (shareable corpus "poster") constants.

Centralizes the tunables for :class:`~opencontractserver.corpuses.models.Artifact`
and :class:`~opencontractserver.corpuses.services.artifact_service.ArtifactService`
so they live with the other domain constants instead of inline magic numbers.
"""

# Bounded retry loop for ``Artifact.save()``'s slug auto-assignment. The slug is
# generated by a non-locking ``.exists()`` loop, so two concurrent creates can
# sample the same candidate before either commits; the second INSERT then trips
# the global ``unique=True`` constraint. ``save()`` catches that IntegrityError
# and re-rolls — but only when the slug was auto-generated — bounded by this
# count (mirrors ``HANDLE_INSERT_RETRY_ATTEMPTS`` for the User handle race).
ARTIFACT_SLUG_RETRY_ATTEMPTS = 5

# Minimum data for a template to be worth offering in the corpus's poster picker
# (``ArtifactService.templates_for_corpus``). A collection with fewer than this
# many dated documents / mapped references would render an empty-looking poster.
_MIN_DATED = 3
_MIN_REFERENCES = 2

# Reject oversized poster uploads *before* the base64 decode allocates the bytes
# in memory (a slow-loris / OOM guard on the otherwise unbounded image field).
# ~10 MB of base64 ≈ 7.5 MB decoded PNG — ample for a poster render.
MAX_ARTIFACT_IMAGE_BASE64_BYTES = 10 * 1024 * 1024

# Reject oversized ``Artifact.config`` payloads (Create/UpdateArtifact) before
# persisting — the field is a free-form GenericScalar JSON blob with no schema
# to naturally bound it, and the WRITE_MEDIUM rate limit only caps request
# *frequency*, not a single payload's size. 64 KB is ample for poster
# configuration (colors, layout toggles, selected metrics).
MAX_ARTIFACT_CONFIG_BYTES = 64 * 1024
