"""
SQLAlchemy модели для банвордов.
"""
from datetime import datetime, timezone
from enum import Enum as PyEnum
from typing import Optional

from sqlalchemy import String, Integer, DateTime, Text, Enum, BigInteger
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column

__all__ = (
    "Base",
    "BanWordType",
    "SpamMode",
    "BanWord",
    "TempBanWord",
    "WhitelistWord",
    "Admin",
    "Setting",
    "SpamStat",
    "SpamLog",
    "AutoComment",
    "Report",
)


class Base(DeclarativeBase):
    """Базовый класс для всех моделей"""
    pass


class BanWordType(str, PyEnum):
    """Типы банвордов"""
    SUBSTRING = "substring"
    LEMMA = "lemma"
    PART = "part"
    CONFLICT_SUBSTRING = "conflict_substring"
    CONFLICT_LEMMA = "conflict_lemma"


class SpamMode(str, PyEnum):
    """Режимы работы спам-фильтра"""
    NORMAL = "normal"
    SILENCE = "silence"
    CONFLICT = "conflict"


class BanWord(Base):
    """
    Постоянные банворды.

    Attributes:
        id: Уникальный ID
        word: Само слово (lowercase)
        type: Тип банворда
        added_by: Telegram ID добавившего админа
        added_at: Дата добавления
        reason: Причина добавления
    """
    __tablename__ = "banwords"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    word: Mapped[str] = mapped_column(String(255), nullable=False, index=True)
    type: Mapped[BanWordType] = mapped_column(
        Enum(BanWordType, native_enum=False),
        nullable=False,
        index=True
    )
    added_by: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
    added_at: Mapped[datetime] = mapped_column(
        DateTime,
        default=datetime.now,
        nullable=False
    )
    reason: Mapped[Optional[str]] = mapped_column(Text, nullable=True)

    def __repr__(self) -> str:
        return f"<BanWord(word='{self.word}', type={self.type})>"


class TempBanWord(Base):
    """
    Временные банворды (с автоудалением).

    Attributes:
        id: Уникальный ID
        word: Само слово
        type: Тип банворда
        added_by: ID админа
        added_at: Дата добавления
        expires_at: Дата истечения
    """
    __tablename__ = "temp_banwords"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    word: Mapped[str] = mapped_column(String(255), nullable=False, index=True)
    type: Mapped[BanWordType] = mapped_column(
        Enum(BanWordType, native_enum=False),
        nullable=False
    )
    added_by: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
    added_at: Mapped[datetime] = mapped_column(
        DateTime,
        default=datetime.now,
        nullable=False
    )
    expires_at: Mapped[datetime] = mapped_column(
        DateTime,
        nullable=False,
        index=True
    )

    def is_expired(self) -> bool:
        """Проверяет, истёк ли срок"""
        return datetime.now() >= self.expires_at

    def __repr__(self) -> str:
        return f"<TempBanWord(word='{self.word}', expires={self.expires_at})>"


class WhitelistWord(Base):
    """
    Белый список (исключения из проверки).

    Attributes:
        id: Уникальный ID
        word: Слово-исключение
        added_by: ID админа
        added_at: Дата добавления
        reason: Причина (например, "ложное срабатывание")
    """
    __tablename__ = "whitelist"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    word: Mapped[str] = mapped_column(String(255), nullable=False, unique=True, index=True)
    added_by: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
    added_at: Mapped[datetime] = mapped_column(
        DateTime,
        default=datetime.now,
        nullable=False
    )
    reason: Mapped[Optional[str]] = mapped_column(Text, nullable=True)

    def __repr__(self) -> str:
        return f"<WhitelistWord(word='{self.word}')>"


class Admin(Base):
    """
    Дополнительные администраторы бота.

    Attributes:
        id: Уникальный ID записи
        user_id: Telegram ID пользователя (уникальный)
        added_by: ID суперадмина, который добавил
        added_at: Дата добавления
        permissions: JSON со списком прав (для будущего)
    """
    __tablename__ = "admins"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    user_id: Mapped[int] = mapped_column(Integer, nullable=False, unique=True, index=True)
    added_by: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
    added_at: Mapped[datetime] = mapped_column(
        DateTime,
        default=datetime.now,
        nullable=False
    )
    permissions: Mapped[Optional[str]] = mapped_column(
        Text,
        default="[]",
        nullable=True
    )

    def __repr__(self) -> str:
        return f"<Admin(user_id={self.user_id})>"


class Setting(Base):
    """
    Настройки и состояния бота.

    Attributes:
        key: Ключ настройки (primary key)
        value: Значение (JSON string)
        updated_at: Дата обновления

    Examples:
        - silence_until: datetime ISO string
        - conflict_until: datetime ISO string
        - spam_mode: "normal"/"silence"/"conflict"
    """
    __tablename__ = "settings"

    key: Mapped[str] = mapped_column(String(100), primary_key=True)
    value: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    updated_at: Mapped[datetime] = mapped_column(
        DateTime,
        default=datetime.now,
        onupdate=datetime.now,
        nullable=False
    )

    def __repr__(self) -> str:
        return f"<Setting(key='{self.key}', value='{self.value}')>"


class SpamStat(Base):
    """
    Статистика удалённых спам-сообщений.

    Attributes:
        id: Уникальный ID
        user_id: Telegram ID отправителя
        username: Username отправителя
        chat_id: ID чата
        message_text: Текст сообщения (до 500 символов)
        matched_word: Слово, по которому сработал фильтр
        match_type: Тип проверки (substring/lemma/part)
        deleted_at: Дата удаления
    """
    __tablename__ = "spam_stats"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    user_id: Mapped[int] = mapped_column(Integer, nullable=False, index=True)
    username: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
    chat_id: Mapped[int] = mapped_column(Integer, nullable=False)
    message_text: Mapped[str] = mapped_column(Text, nullable=False)
    matched_word: Mapped[str] = mapped_column(String(255), nullable=False)
    match_type: Mapped[str] = mapped_column(String(50), nullable=False)
    deleted_at: Mapped[datetime] = mapped_column(
        DateTime,
        default=datetime.now,
        nullable=False,
        index=True
    )

    def __repr__(self) -> str:
        return f"<SpamStat(user_id={self.user_id}, word='{self.matched_word}')>"


class SpamLog(Base):
    """Модель для логирования срабатываний спам-фильтра"""
    __tablename__ = "spam_logs"

    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
    user_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
    username: Mapped[str] = mapped_column(String(255), nullable=True)
    chat_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
    message_text: Mapped[str] = mapped_column(Text, nullable=True)
    matched_word: Mapped[str] = mapped_column(String(255), nullable=True)  # <-- Должно быть!
    match_type: Mapped[str] = mapped_column(String(50), nullable=True)     # <-- Должно быть!
    timestamp: Mapped[datetime] = mapped_column(
        DateTime,
        default=lambda: datetime.now(timezone.utc)
    )

class AutoComment(Base):
    """
    Настройки автокомментариев для каналов.

    Attributes:
        id: Уникальный ID
        channel_id: ID канала (-100...)
        text: Текст комментария (HTML)
        button_text: Текст кнопки
        button_url: URL кнопки
        photo_url: URL фото для preview
        is_enabled: Включены ли автокомментарии для этого канала
        created_at: Дата создания
        updated_at: Дата последнего обновления
        updated_by: ID админа, который последним изменил
    """
    __tablename__ = "auto_comments"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    channel_id: Mapped[int] = mapped_column(BigInteger, nullable=False, unique=True, index=True)
    text: Mapped[str] = mapped_column(Text, nullable=False)
    button_text: Mapped[str] = mapped_column(String(100), nullable=False)
    button_url: Mapped[str] = mapped_column(String(500), nullable=False)
    photo_url: Mapped[str] = mapped_column(String(500), nullable=False)
    is_enabled: Mapped[bool] = mapped_column(Integer, default=1, nullable=False)
    created_at: Mapped[datetime] = mapped_column(
        DateTime,
        default=lambda: datetime.now(timezone.utc),
        nullable=False
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime,
        default=lambda: datetime.now(timezone.utc),
        onupdate=lambda: datetime.now(timezone.utc),
        nullable=False
    )
    updated_by: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)

    def __repr__(self) -> str:
        return f"<AutoComment(channel_id={self.channel_id}, enabled={self.is_enabled})>"
        

class Report(Base):
    """
    Модель для хранения статистики репортов.

    Attributes:
        id: Уникальный ID репорта
        report_id: Строковый ID репорта (timestamp)
        reporter_id: ID пользователя, который пожаловался
        reporter_username: Username жалобщика
        reported_user_id: ID пользователя, на которого пожаловались
        reported_username: Username нарушителя
        chat_id: ID чата, где произошло нарушение
        chat_title: Название чата
        message_id: ID сообщения-нарушения
        message_thread_id: ID топика (если есть)
        message_text: Текст сообщения (до 500 символов)
        reason: Причина жалобы
        status: Статус репорта (pending, closed, banned, deleted)
        processed_by: ID админа, который обработал
        created_at: Дата создания репорта
        processed_at: Дата обработки
    """
    __tablename__ = "reports"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    report_id: Mapped[str] = mapped_column(String(50), nullable=False, unique=True, index=True)

    # Информация о жалобщике
    reporter_id: Mapped[int] = mapped_column(BigInteger, nullable=False, index=True)
    reporter_username: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)

    # Информация о нарушителе
    reported_user_id: Mapped[int] = mapped_column(BigInteger, nullable=False, index=True)
    reported_username: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)

    # Информация о чате и сообщении
    chat_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
    chat_title: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
    message_id: Mapped[int] = mapped_column(Integer, nullable=False)
    message_thread_id: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
    message_text: Mapped[Optional[str]] = mapped_column(Text, nullable=True)

    # Причина и статус
    reason: Mapped[str] = mapped_column(Text, nullable=False)
    status: Mapped[str] = mapped_column(
        String(20),
        default="pending",
        nullable=False,
        index=True
    )  # pending, closed, banned, deleted

    # Обработка
    processed_by: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
    created_at: Mapped[datetime] = mapped_column(
        DateTime,
        default=lambda: datetime.now(timezone.utc),
        nullable=False,
        index=True
    )
    processed_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)

    def __repr__(self) -> str:
        return f"<Report(id={self.report_id}, reporter={self.reporter_id}, reported={self.reported_user_id})>"
