"""
Фоновые задачи для автоматической очистки и обслуживания бота
"""
import asyncio
from datetime import datetime
from pathlib import Path
import shutil

from database import get_manager
from middleware.loggers import logger
from configs import settings

__all__ = ('cleanup_expired_banwords', 'cleanup_spam_stats', 'auto_backup_database', 'start_background_tasks', 'check_system_health')


async def cleanup_expired_banwords() -> None:
    """
    Периодически удаляет истёкшие временные банворды.

    Запускается каждый час и проверяет все временные слова.
    Удаляет те, у которых истёк срок действия.
    """
    logger.info("🔄 Запущена задача автоочистки временных банвордов", log_type="CLEANUP")

    manager = get_manager()

    while True:
        try:
            # Ждём 1 час между проверками
            await asyncio.sleep(3600)

            # Выполняем очистку
            deleted = await manager.cleanup_expired_temp_words()

            if deleted > 0:
                logger.info(
                    f"✅ Очищено {deleted} истёкших временных банвордов",
                    log_type="CLEANUP"
                )
            else:
                logger.debug(
                    "✓ Проверка временных банвордов: истёкших не найдено",
                    log_type="CLEANUP"
                )

        except Exception as e:
            logger.error(
                f"❌ Ошибка в задаче очистки банвордов: {e}",
                log_type="CLEANUP"
            )
            # При ошибке ждём 5 минут перед следующей попыткой
            await asyncio.sleep(300)


async def cleanup_spam_stats(max_age_days: int = 30) -> None:
    """
    Очищает старую статистику антиспама.

    Запускается каждые 24 часа и удаляет записи старше max_age_days дней.

    Args:
        max_age_days: Возраст записей для удаления (по умолчанию 30 дней)
    """
    logger.info(
        f"🔄 Запущена задача очистки статистики (возраст > {max_age_days} дней)",
        log_type="CLEANUP"
    )

    from bot.middlewares.spam_mdw import spam_stats

    while True:
        try:
            # Ждём 24 часа между проверками
            await asyncio.sleep(86400)

            # Очищаем старую статистику
            max_age_seconds = max_age_days * 86400
            deleted = spam_stats.cleanup(max_age=max_age_seconds)

            if deleted > 0:
                logger.info(
                    f"✅ Очищена статистика: {deleted} неактивных пользователей",
                    log_type="CLEANUP"
                )
            else:
                logger.debug(
                    "✓ Проверка статистики: старых записей не найдено",
                    log_type="CLEANUP"
                )

        except Exception as e:
            logger.error(
                f"❌ Ошибка в задаче очистки статистики: {e}",
                log_type="CLEANUP"
            )
            await asyncio.sleep(3600)  # При ошибке ждём 1 час


async def auto_backup_database(backup_interval_hours: int = 24, keep_backups: int = 7) -> None:
    """
    Автоматически создаёт резервные копии базы данных.

    Args:
        backup_interval_hours: Интервал между бэкапами (по умолчанию 24 часа)
        keep_backups: Количество хранимых копий (по умолчанию 7)
    """
    logger.info(
        f"🔄 Запущена задача автобэкапа (каждые {backup_interval_hours}ч, хранить {keep_backups})",
        log_type="CLEANUP"
    )

    while True:
        try:
            # Ждём указанное время
            await asyncio.sleep(backup_interval_hours * 3600)

            # Путь к базе данных
            db_path = Path(settings.DATABASE_PATH)

            if not db_path.exists():
                logger.warning(
                    f"⚠️ База данных не найдена: {db_path}",
                    log_type="CLEANUP"
                )
                continue

            # Создаём папку для бэкапов
            backup_dir = Path("backups")
            backup_dir.mkdir(exist_ok=True)

            # Имя файла бэкапа с датой и временем
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            backup_path = backup_dir / f"banwords_backup_{timestamp}.db"

            # Копируем базу данных
            shutil.copy2(db_path, backup_path)

            # Получаем размер файла
            backup_size = backup_path.stat().st_size / 1024  # KB

            logger.info(
                f"✅ Создан backup: {backup_path.name} ({backup_size:.1f} KB)",
                log_type="CLEANUP"
            )

            # Удаляем старые бэкапы (оставляем только последние N)
            backups = sorted(backup_dir.glob("banwords_backup_*.db"))

            if len(backups) > keep_backups:
                old_backups = backups[:-keep_backups]

                for old_backup in old_backups:
                    old_backup.unlink()
                    logger.debug(
                        f"🗑️ Удалён старый backup: {old_backup.name}",
                        log_type="CLEANUP"
                    )

                logger.info(
                    f"✓ Удалено старых бэкапов: {len(old_backups)}",
                    log_type="CLEANUP"
                )

        except Exception as e:
            logger.error(
                f"❌ Ошибка создания backup: {e}",
                log_type="CLEANUP"
            )
            await asyncio.sleep(3600)  # При ошибке ждём 1 час


async def check_system_health() -> None:
    """
    Мониторинг здоровья системы.

    Проверяет каждые 5 минут:
    - Размер базы данных
    - Количество записей в БД
    - Использование памяти (статистика антиспама)
    """
    logger.info("🔄 Запущена задача мониторинга системы", log_type="CLEANUP")

    manager = get_manager()

    while True:
        try:
            await asyncio.sleep(300)  # 5 минут

            # Проверяем размер БД
            db_path = Path(settings.DATABASE_PATH)
            if db_path.exists():
                db_size_mb = db_path.stat().st_size / (1024 * 1024)

                if db_size_mb > 100:  # Если больше 100 MB
                    logger.warning(
                        f"⚠️ Большой размер БД: {db_size_mb:.2f} MB",
                        log_type="CLEANUP"
                    )

            # Проверяем количество временных слов
            stats = await manager.get_stats()
            temp_count = stats.get('temp_total', 0)

            if temp_count > 100:  # Если больше 100 временных слов
                logger.warning(
                    f"⚠️ Много временных банвордов: {temp_count}",
                    log_type="CLEANUP"
                )

            # Проверяем статистику антиспама
            from bot.middlewares.spam_mdw import spam_stats
            spam_summary = spam_stats.get_stats_summary()

            active_blocks = spam_summary.get('active_blocks', 0)
            if active_blocks > 10:
                logger.warning(
                    f"⚠️ Много активных блокировок: {active_blocks}",
                    log_type="CLEANUP"
                )

        except Exception as e:
            logger.error(
                f"❌ Ошибка в задаче мониторинга: {e}",
                log_type="CLEANUP"
            )
            await asyncio.sleep(600)  # При ошибке ждём 10 минут


def start_background_tasks() -> list[asyncio.Task]:
    """
    Запускает все фоновые задачи.

    Returns:
        List[asyncio.Task]: Список запущенных задач
    """
    tasks = []

    # 1. Автоочистка временных банвордов (каждый час)
    task1 = asyncio.create_task(cleanup_expired_banwords())
    tasks.append(task1)
    logger.info("✅ Задача 'cleanup_expired_banwords' запущена", log_type="STARTUP")

    # 2. Очистка старой статистики (каждые 24 часа)
    task2 = asyncio.create_task(cleanup_spam_stats(max_age_days=30))
    tasks.append(task2)
    logger.info("✅ Задача 'cleanup_spam_stats' запущена", log_type="STARTUP")

    # 3. Автобэкап базы данных (каждые 24 часа, хранить 7 копий)
    task3 = asyncio.create_task(auto_backup_database(backup_interval_hours=24, keep_backups=7))
    tasks.append(task3)
    logger.info("✅ Задача 'auto_backup_database' запущена", log_type="STARTUP")

    # 4. Мониторинг здоровья системы (каждые 5 минут)
    task4 = asyncio.create_task(check_system_health())
    tasks.append(task4)
    logger.info("✅ Задача 'check_system_health' запущена", log_type="STARTUP")

    logger.success(
        f"🚀 Все фоновые задачи запущены: {len(tasks)} шт.",
        log_type="STARTUP"
    )

    return tasks
