"""
patches.py — патчи Telethon для подавления шума MTProto/update_loop.
Этот модуль применяет патчи сразу при импорте.
Можно менять/переперезапускать независимо, но требует перезапуска бота.
"""
import sys

try:
    from telethon.errors.rpcerrorlist import FrozenMethodInvalidError as _FrozenMethodInvalidError
except ImportError:
    class _FrozenMethodInvalidError(Exception): pass  # type: ignore
FrozenMethodInvalidError = _FrozenMethodInvalidError

try:
    from telethon.errors.rpcerrorlist import FrozenParticipantMissingError as _FrozenParticipantMissingError
except ImportError:
    class _FrozenParticipantMissingError(Exception): pass  # type: ignore
FrozenParticipantMissingError = _FrozenParticipantMissingError

try:
    from telethon.errors.rpcerrorlist import PersistentTimestampOutdatedError as _PersistentTimestampOutdatedError
except ImportError:
    class _PersistentTimestampOutdatedError(Exception): pass  # type: ignore
PersistentTimestampOutdatedError = _PersistentTimestampOutdatedError


def _patch_telethon_update_loop():
    """Патч Telethon: подавляем FrozenParticipantMissingError/PersistentTimestampOutdated/SecurityError в update_loop."""
    try:
        import telethon.client.updates as _tcu
        _orig_update_loop = _tcu.UpdateMethods._update_loop

        async def _safe_update_loop(self):
            while self.is_connected():
                try:
                    await _orig_update_loop(self)
                except (FrozenParticipantMissingError, _FrozenParticipantMissingError):
                    pass
                except Exception as _ue:
                    _name = type(_ue).__name__
                    _msg  = str(_ue)
                    if any(k in _name for k in ("Frozen", "PersistentTimestamp", "AuthKey", "SessionRevoked")):
                        pass
                    elif any(k in _msg for k in (
                        "very old message",
                        "Too many messages had to be ignored",
                        "wrong session ID",
                        "SecurityError",
                        "ignored consecutively",
                    )):
                        pass
                    else:
                        break

        _tcu.UpdateMethods._update_loop = _safe_update_loop
    except Exception:
        pass


def _patch_mtproto_sender():
    """Патч MTProtoSender: подавляем SecurityError/old-message на уровне класса."""
    try:
        import telethon.network.mtproto_sender as _mts
        _OrigSender = _mts.MTProtoSender

        _orig_handle_recv = getattr(_OrigSender, "_handle_recv", None)
        if _orig_handle_recv is None:
            return

        async def _safe_handle_recv(self, *a, **kw):
            try:
                return await _orig_handle_recv(self, *a, **kw)
            except Exception as _e:
                _ename = type(_e).__name__
                _emsg  = str(_e)
                _is_noise = any(k in _emsg for k in (
                    "very old message",
                    "Too many messages had to be ignored",
                    "wrong session ID",
                    "SecurityError",
                ))
                if _is_noise or "Security" in _ename:
                    return
                raise

        _OrigSender._handle_recv = _safe_handle_recv

    except Exception:
        pass


# Применяем патчи сразу при импорте
_patch_telethon_update_loop()
_patch_mtproto_sender()

# Применяем EventLoop policy на Windows
if sys.platform.startswith('win'):
    try:
        import asyncio
        asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
    except Exception:
        pass
