"""Domain model for a Telegram message.

Based on the Telegram TL schema for the ``message`` constructor (Layer 214):
https://core.telegram.org/constructor/message
"""
from __future__ import annotations

from datetime import datetime
from typing import Any

from repo_core.base.models import DomainModel


class TelegramMessage(DomainModel):
    """Strongly-typed representation of a persisted Telegram message record.

    Keyed by the natural Telegram business key ``(peer_id, message_id)``.
    All fields are persisted to every backend (DB, search, warehouse).
    Nested compound types (MessageFwdHeader, MessageMedia, etc.) are
    stored as ``dict[str, Any] | None`` via JSONB/JSON columns.

    All timestamp fields use timezone-aware UTC ``datetime`` objects.

    Usage::

        msg = TelegramMessage.from_db({
            "peer_id": 123,
            "message_id": 42,
            "message_sent_at": datetime(2024, 6, 15, 10, 30, tzinfo=timezone.utc),
            "message": "Hello, World!",
        })
        row = msg.to_db()
    """

    message_id: int
    peer_id: int
    message_sent_at: datetime
    message: str = ""

    out: bool | None = False
    mentioned: bool | None = False
    media_unread: bool | None = False
    silent: bool | None = False
    post: bool | None = False
    from_scheduled: bool | None = False
    legacy: bool | None = False
    edit_hide: bool | None = False
    pinned: bool | None = False
    noforwards: bool | None = False
    invert_media: bool | None = False

    offline: bool | None = False
    paid_suggested_post_stars: bool | None = False
    paid_suggested_post_ton: bool | None = False

    from_id: dict[str, Any] | None = None
    from_boosts_applied: int | None = None
    saved_peer_id: dict[str, Any] | None = None
    fwd_from: dict[str, Any] | None = None
    via_bot_id: int | None = None
    via_business_bot_id: int | None = None
    reply_to: dict[str, Any] | None = None
    media: dict[str, Any] | None = None
    reply_markup: dict[str, Any] | None = None
    details: list[dict[str, Any]] | None = None
    views: int | None = None
    forwards: int | None = None
    replies: dict[str, Any] | None = None
    edit_date: datetime | None = None
    post_author: str | None = None
    grouped_id: int | None = None
    reactions: dict[str, Any] | None = None
    restriction_reason: list[dict[str, Any]] | None = None
    ttl_period: int | None = None
    quick_reply_shortcut_id: int | None = None
    effect: dict[str, Any] | None = None
    factcheck: dict[str, Any] | None = None
    report_delivery_until_date: datetime | None = None
    paid_message_stars: int | None = None
    suggested_post: dict[str, Any] | None = None

    crawled_at: datetime | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None

    # Per-backend field sets — all fields persisted
    _db_include: set[str] = {
        "message_id",
        "peer_id",
        "message_sent_at",
        "message",
        "out",
        "mentioned",
        "media_unread",
        "silent",
        "post",
        "from_scheduled",
        "legacy",
        "edit_hide",
        "pinned",
        "noforwards",
        "invert_media",
        "offline",
        "paid_suggested_post_stars",
        "paid_suggested_post_ton",
        "from_id",
        "from_boosts_applied",
        "saved_peer_id",
        "fwd_from",
        "via_bot_id",
        "via_business_bot_id",
        "reply_to",
        "media",
        "reply_markup",
        "details",
        "views",
        "forwards",
        "replies",
        "edit_date",
        "post_author",
        "grouped_id",
        "reactions",
        "restriction_reason",
        "ttl_period",
        "quick_reply_shortcut_id",
        "effect",
        "factcheck",
        "report_delivery_until_date",
        "paid_message_stars",
        "suggested_post",
        "crawled_at",
        "created_at",
        "updated_at",
    }

    _search_include: set[str] = {
        "message_id",
        "peer_id",
        "message_sent_at",
        "message",
        "out",
        "mentioned",
        "media_unread",
        "silent",
        "post",
        "from_scheduled",
        "legacy",
        "edit_hide",
        "pinned",
        "noforwards",
        "invert_media",
        "offline",
        "paid_suggested_post_stars",
        "paid_suggested_post_ton",
        "from_id",
        "from_boosts_applied",
        "saved_peer_id",
        "fwd_from",
        "via_bot_id",
        "via_business_bot_id",
        "reply_to",
        "media",
        "reply_markup",
        "details",
        "views",
        "forwards",
        "replies",
        "edit_date",
        "post_author",
        "grouped_id",
        "reactions",
        "restriction_reason",
        "ttl_period",
        "quick_reply_shortcut_id",
        "effect",
        "factcheck",
        "report_delivery_until_date",
        "paid_message_stars",
        "suggested_post",
        "crawled_at",
        "created_at",
        "updated_at",
    }

    _warehouse_include: set[str] = {
        "message_id",
        "peer_id",
        "message_sent_at",
        "message",
        "out",
        "mentioned",
        "media_unread",
        "silent",
        "post",
        "from_scheduled",
        "legacy",
        "edit_hide",
        "pinned",
        "noforwards",
        "invert_media",
        "offline",
        "paid_suggested_post_stars",
        "paid_suggested_post_ton",
        "from_id",
        "from_boosts_applied",
        "saved_peer_id",
        "fwd_from",
        "via_bot_id",
        "via_business_bot_id",
        "reply_to",
        "media",
        "reply_markup",
        "details",
        "views",
        "forwards",
        "replies",
        "edit_date",
        "post_author",
        "grouped_id",
        "reactions",
        "restriction_reason",
        "ttl_period",
        "quick_reply_shortcut_id",
        "effect",
        "factcheck",
        "report_delivery_until_date",
        "paid_message_stars",
        "suggested_post",
        "crawled_at",
        "created_at",
        "updated_at",
    }
