"""
Django ORM models for the Discord audit module.

Public API: every model class, enum, manager, and field-length
constant the rest of the codebase imports lives at this path
(``aa_discord_audit.models``). The module is split internally
into private ``_<topic>.py`` files for readability; importers
should always use this package's flat namespace, not the private
submodules.

Append-only enforcement runs in two layers, applied to ``AuditRun``,
``AuditFinding``, ``ConfigChangeLog``, and ``AuditInvocation``:

1. ``AppendOnlyManager`` (via ``Manager.from_queryset(AppendOnlyQuerySet)``)
   blocks ``Model.objects.update()``,
   ``Model.objects.filter(...).update()``, and ``bulk_update``.
2. ``AppendOnlyModelMixin.save()`` validates that an existing-row
   update only changes fields listed in
   ``_APPEND_ONLY_UPDATABLE_FIELDS``. Per-model overrides spell
   out the allow-list.

The accepted residual is raw SQL through ``connection.cursor()``
which bypasses both layers; this is the documented escape hatch
for forensic ops and not used by the module itself today.

Note: ``DiscordIdentity`` is *not* append-only — it is a mutable
observation map and supports plain ORM updates (see ``audit.py``
where ``last_seen_in_guild_at`` is bumped via
``DiscordIdentity.objects.filter(uid__in=…).update(...)``).
"""

from __future__ import annotations

from ._append_only import (
    AppendOnlyManager,
    AppendOnlyModelMixin,
    AppendOnlyQuerySet,
    BulkBlockingManager,
)
from ._audit import AuditFinding, AuditRun
from ._changelog import AuditInvocation, ConfigChangeLog
from ._constants import (
    DISCORD_NAME_MAX_LENGTH,
    DISCORD_ROLE_NAME_MAX_LENGTH,
    DJANGO_USERNAME_MAX_LENGTH,
    ENUM_MAX_LENGTH,
    MODEL_LABEL_MAX_LENGTH,
    OBJECT_PK_MAX_LENGTH,
    REASON_ENUM_MAX_LENGTH,
)
from ._enums import (
    AuditFindingState,
    AuditRunState,
    ConfigAction,
    FindingSkipReason,
    IdentitySource,
    InvocationRefusal,
    OrphanAction,
    OrphanCategory,
    RunTrigger,
)
from ._identity import DiscordIdentity
from ._kicks import PendingKick
from ._operator_config import (
    BotAccountUid,
    FindingActionOverride,
    InitialAuditAcknowledgement,
    ManagedRoleException,
    ProtectedDiscordMember,
)

__all__ = [
    "DISCORD_NAME_MAX_LENGTH",
    "DISCORD_ROLE_NAME_MAX_LENGTH",
    "DJANGO_USERNAME_MAX_LENGTH",
    "ENUM_MAX_LENGTH",
    "MODEL_LABEL_MAX_LENGTH",
    "OBJECT_PK_MAX_LENGTH",
    "REASON_ENUM_MAX_LENGTH",
    "AppendOnlyManager",
    "AppendOnlyModelMixin",
    "AppendOnlyQuerySet",
    "AuditFinding",
    "AuditFindingState",
    "AuditInvocation",
    "AuditRun",
    "AuditRunState",
    "BotAccountUid",
    "BulkBlockingManager",
    "ConfigAction",
    "ConfigChangeLog",
    "DiscordIdentity",
    "FindingActionOverride",
    "FindingSkipReason",
    "IdentitySource",
    "InitialAuditAcknowledgement",
    "InvocationRefusal",
    "ManagedRoleException",
    "OrphanAction",
    "OrphanCategory",
    "PendingKick",
    "ProtectedDiscordMember",
    "RunTrigger",
]
