"""Flood control and anti-raid detection."""
from __future__ import annotations

import time
from collections import deque

from telegram import ChatPermissions
from telegram.constants import ParseMode
from telegram.error import BadRequest, Forbidden
from telegram.ext import ContextTypes

from bot import db
from bot.config import DEFAULT_FLOOD_LIMIT

_NO_PERMS = ChatPermissions(
    can_send_messages=False,
    can_send_audios=False,
    can_send_documents=False,
    can_send_photos=False,
    can_send_videos=False,
    can_send_video_notes=False,
    can_send_voice_notes=False,
    can_send_polls=False,
    can_send_other_messages=False,
    can_add_web_page_previews=False,
    can_change_info=False,
    can_invite_users=False,
    can_pin_messages=False,
    can_manage_topics=False,
    is_member=True,
)

# Track recent messages per (chat_id, user_id) for flood detection
_flood_tracker: dict[tuple[int, int], deque[float]] = {}
ANTI_RAID_TRACKER: dict[int, list[float]] = {}
_CLEANUP_INTERVAL: float = 300.0
_LAST_CLEANUP: float = 0.0


def cleanup_old_trackers() -> None:
    global _LAST_CLEANUP
    now = time.time()
    if now - _LAST_CLEANUP < _CLEANUP_INTERVAL:
        return
    _LAST_CLEANUP = now
    cutoff = now - 3600
    for key in list(_flood_tracker.keys()):
        timestamps = _flood_tracker[key]
        while timestamps and timestamps[0] < cutoff:
            timestamps.popleft()
        if not timestamps:
            del _flood_tracker[key]
    for cid in list(ANTI_RAID_TRACKER.keys()):
        ANTI_RAID_TRACKER[cid][:] = [t for t in ANTI_RAID_TRACKER[cid] if now - t < 300]
        if not ANTI_RAID_TRACKER[cid]:
            del ANTI_RAID_TRACKER[cid]


async def check_flood(bot, context, message, chat_id: int, user_id: int, settings: dict) -> bool:
    """Check if user is flooding. If so, take configured action. Returns True if action was taken."""
    limit = int(settings.get("flood_limit", DEFAULT_FLOOD_LIMIT))
    window = int(settings.get("flood_time", 10))
    mode = settings.get("flood_mode", "mute")

    if not settings.get("antiflood", False):
        return False

    key = (chat_id, user_id)
    now = time.time()
    arr = _flood_tracker.setdefault(key, deque())
    arr.append(now)
    while arr and now - arr[0] > window:
        arr.popleft()

    if len(arr) >= limit:
        arr.clear()
        flood_duration = int(settings.get("flood_duration", 0)) or 3600
        try:
            if mode == "ban":
                await bot.ban_chat_member(chat_id, user_id)
                action = "بن"
            elif mode == "tban":
                await bot.ban_chat_member(chat_id, user_id, until_date=int(time.time() + flood_duration))
                action = f"بن موقت {flood_duration // 60}د"
            elif mode == "kick":
                await bot.ban_chat_member(chat_id, user_id)
                await bot.unban_chat_member(chat_id, user_id)
                action = "کیک"
            elif mode == "tmute":
                until = int(time.time() + flood_duration)
                await bot.restrict_chat_member(chat_id, user_id, permissions=_NO_PERMS, until_date=until)
                action = f"سکوت موقت {flood_duration // 60}د"
            else:  # mute
                await bot.restrict_chat_member(
                    chat_id,
                    user_id,
                    permissions=_NO_PERMS,
                )
                action = "سکوت"
            await message.reply_text(
                f"🌊 کاربر به دلیل ارسال رگباری {action} شد.",
                parse_mode=ParseMode.HTML,
            )
            return True
        except (BadRequest, Forbidden):
            return False
    return False


async def check_antiraid(bot, context, message, chat_id: int, user_id: int) -> bool:
    """Detect and stop mass joins (anti-raid)."""
    settings = await db.get_all_settings(chat_id)
    if not settings.get("antiraid", False):
        return False
    now = time.time()
    arr = ANTI_RAID_TRACKER.setdefault(chat_id, [])
    arr.append(now)
    arr[:] = [t for t in arr if now - t < 60]
    if len(arr) >= 5:
        await db.set_setting(chat_id, "antiraid_locked", True)
        try:
            await bot.set_chat_permissions(
                chat_id,
                permissions=ChatPermissions(
                    can_send_messages=False,
                    can_send_audios=False,
                    can_send_documents=False,
                    can_send_photos=False,
                    can_send_videos=False,
                    can_send_video_notes=False,
                    can_send_voice_notes=False,
                    can_send_polls=False,
                    can_send_other_messages=False,
                    can_add_web_page_previews=False,
                    can_change_info=False,
                    can_invite_users=False,
                    can_pin_messages=False,
                    can_manage_topics=False,
                ),
            )
            await message.reply_text("🌀 ریپ شناسایی شد! گروه موقتاً قفل شد.")
        except (BadRequest, Forbidden):
            pass
        return True
    return False
