"""Structural Protocol interfaces shared across the platform.

These are *structural* (duck-typed) protocols — they do not impose any
inheritance requirement.  Any class that exposes the described attributes
automatically satisfies the protocol at type-check time (PEP 544).

No imports from ``simorgh.apps.*`` — these are framework-level contracts.

Usage::

    from simorgh.shared.protocols import TenantScoped

    def process(obj: TenantScoped) -> None:
        tenant_pk = obj.tenant_id
"""
from __future__ import annotations

from typing import Any, Iterator, Protocol, runtime_checkable

__all__ = [
    "TenantScoped",
    "Auditable",
    "Searchable",
    "SoftDeletable",
    "Orderable",
    "HasPublicId",
]


@runtime_checkable
class TenantScoped(Protocol):
    """Object that is scoped to a single tenant.

    Structural counterpart of :class:`simorgh.core.models.TenantScopedModel`.
    """

    tenant_id: int


@runtime_checkable
class Auditable(Protocol):
    """Object that records creation and modification timestamps.

    Structural counterpart of :class:`simorgh.core.models.AuditedModel`.
    """

    created_at: Any  # datetime
    updated_at: Any  # datetime
    created_by_id: int | None
    updated_by_id: int | None


@runtime_checkable
class Searchable(Protocol):
    """Object that exposes a plain-text search representation.

    Implement ``search_vector()`` to return the text(s) that should be
    indexed for full-text search.
    """

    def search_vector(self) -> str | list[str]:
        """Return the text content used for FTS indexing."""
        ...


@runtime_checkable
class SoftDeletable(Protocol):
    """Object that supports soft deletion.

    Structural counterpart of :class:`simorgh.core.models.SoftDeleteModel`.
    """

    is_deleted: bool
    deleted_at: Any  # datetime | None

    def delete(self, *args: Any, **kwargs: Any) -> tuple[int, dict[str, int]]:
        """Mark record as deleted (soft delete)."""
        ...

    def hard_delete(self, *args: Any, **kwargs: Any) -> tuple[int, dict[str, int]]:
        """Permanently remove the record from the database."""
        ...


@runtime_checkable
class Orderable(Protocol):
    """Object that participates in explicit sort ordering.

    Structural counterpart of :class:`simorgh.core.models.OrderedModel`.
    """

    sort_order: int


@runtime_checkable
class HasPublicId(Protocol):
    """Object that exposes an external-facing UUID.

    Structural counterpart of :class:`simorgh.core.models.UUIDModel`.
    """

    public_id: Any  # uuid.UUID


# ---------------------------------------------------------------------------
# Composite convenience aliases
# ---------------------------------------------------------------------------

class TenantEntity(TenantScoped, Auditable, HasPublicId, Protocol):
    """A full tenant-owned entity with timestamps and a public UUID.

    Most DMS / workflow domain objects should satisfy this protocol.
    """
    ...


class EventLike(Protocol):
    """Minimal interface for domain events / outbox messages."""

    event_type: str
    payload: dict[str, Any]

    def serialize(self) -> dict[str, Any]:
        """Return a JSON-serializable dict for message brokering."""
        ...
