"""
accounts_folder.py — синхронизация папки "Аккаунты/" для наглядности.
Создаёт подпапки по статусам и раскладывает ярлыки/инфо файлы.
Вызывается при старте и периодически из scheduler.
"""
import logging
import shutil
from pathlib import Path

logger = logging.getLogger("telepush")

# Категории аккаунтов
CATEGORIES = {
    "\u0412 \u0440\u0430\u0431\u043e\u0442\u0435": lambda acc: not acc.dead and not acc.frozen and not acc.spam_blocked,
    "\u0417\u0430\u043c\u043e\u0440\u043e\u0437\u043a\u0430": lambda acc: acc.frozen and not acc.dead,
    "\u041c\u0451\u0440\u0442\u0432\u044b\u0435": lambda acc: acc.dead and not acc.frozen,
    "\u0412 \u0441\u043f\u0430\u043c": lambda acc: acc.spam_blocked and not acc.dead and not acc.frozen and not getattr(acc, 'spam_permanent', False),
    "\u0412\u0435\u0447\u043d\u044b\u0439 \u0441\u043f\u0430\u043c": lambda acc: acc.spam_blocked and getattr(acc, 'spam_permanent', False),
}


def get_accounts_root() -> Path:
    """Корень папки Аккаунты/ — из config."""
    from config import ACCOUNTS_DIR
    return ACCOUNTS_DIR


def ensure_accounts_folder():
    """Создаёт папку Аккаунты/ со всеми подпапками при старте."""
    root = get_accounts_root()
    logger.info("[accounts_folder] Creating at: %s", root)
    try:
        for cat in CATEGORIES:
            (root / cat).mkdir(parents=True, exist_ok=True)
        # Спец-папки для ручного назначения роли (sync_accounts_folder их не
        # трогает — туда юзер сам кладёт акки).
        for special in ("Мониторинг", "Прогрев"):
            (root / special).mkdir(parents=True, exist_ok=True)
        # Папки куда инвайтер раскладывает акки по типу проблемы после работы.
        # Создаются заранее, чтобы клиент сразу видел структуру в Аккаунты/.
        invite_subfolders = [
            "После инвайта/Спамблок",
            "После инвайта/Слишком свежая сессия для изменения прав",
            "После инвайта/Лимит на поиск по номерам",
            "После инвайта/Большой FloodWait",
            "После инвайта/Заморозка",
            "После инвайта/Мёртвые",
        ]
        for sub in invite_subfolders:
            (root / sub).mkdir(parents=True, exist_ok=True)
        logger.info("[accounts_folder] OK")
    except Exception as e:
        logger.error("[accounts_folder] Failed: %s", e)


def sync_accounts_folder(accounts: dict):
    """Перемещает .session/.json файлы между папками по статусу аккаунтов.

    Спец-папки (Мониторинг, Прогрев и любые другие НЕ из CATEGORIES) трогаем
    только если файл там лежит руками клиента — не двигаем и не переписываем
    folder_name. Иначе sync ломал ручные переносы: клиент кидал акк в
    Мониторинг/, sync видел «акк живой» → ставил folder_name='В работе',
    UI больше не показывал акк во вкладке Мониторинг, кнопка «Перенести»
    промахивалась мимо файла.
    """
    root = get_accounts_root()

    try:
        for cat in CATEGORIES:
            (root / cat).mkdir(parents=True, exist_ok=True)

        moved = 0
        # Кешируем real-расположение всех .session файлов через rglob —
        # один проход по диску вместо resolve() на каждый акк. Раньше
        # парентом считали через parent.parent == root, ломалось когда:
        # - файл в Мониторинг/ (parent.parent==root, OK), Мониторинг/Подпапка/ (FAIL),
        # - parent / root отличаются case или separator на Windows.
        actual_folder_by_phone = {}
        try:
            for f in root.rglob("*.session"):
                if not f.is_file() or not f.stem.isdigit():
                    continue
                try:
                    rel = f.relative_to(root)
                    if len(rel.parts) >= 2:
                        # Первая часть relative-path — это «top-level» категория
                        # внутри Аккаунты/. Например для «После инвайта/Спамблок/79.session»
                        # это «После инвайта» (НЕ в CATEGORIES → не трогаем).
                        actual_folder_by_phone[f.stem] = rel.parts[0]
                except Exception:
                    pass
        except Exception:
            pass

        for phone, acc in accounts.items():
            # Источник истины — где файл реально лежит на диске.
            actual_folder = actual_folder_by_phone.get(phone)
            if actual_folder and actual_folder not in CATEGORIES:
                # Файл в спец-папке (Мониторинг/Прогрев/После инвайта/что-то кастомное).
                # Не двигаем по категориям, только синхронизируем folder_name.
                if acc.folder_name != actual_folder:
                    acc.folder_name = actual_folder
                # Прогрев: warmup-флаг должен следовать за папкой. Без этого
                # клиент кидает свежие .session в Аккаунты/Прогрев/ без рестарта,
                # api_warmup_start считает их по folder_name (старт ОК), но
                # build_warmup_pairs фильтрует по acc.warmup → "got 1".
                if actual_folder in ("Прогрев", "Warmup"):
                    acc.warmup = True
                if actual_folder in ("Мониторинг", "Monitoring"):
                    acc.monitor = True
                continue

            # Стандартная синхронизация по статусу.
            category = "В работе"
            for cat_name, check_fn in CATEGORIES.items():
                if check_fn(acc):
                    category = cat_name
                    break

            target_dir = root / category

            # Ищем файлы в других папках CATEGORIES и перемещаем
            for other_cat in CATEGORIES:
                if other_cat == category:
                    continue
                other_dir = root / other_cat
                for ext in ('.session', '.json'):
                    src = other_dir / f"{phone}{ext}"
                    dst = target_dir / f"{phone}{ext}"
                    if src.exists() and not dst.exists():
                        try:
                            shutil.move(str(src), str(dst))
                            moved += 1
                            # Обновляем путь в Account
                            if ext == '.session' and hasattr(acc, 'session_path'):
                                acc.session_path = dst
                            elif ext == '.json' and hasattr(acc, 'json_path'):
                                acc.json_path = dst
                        except Exception:
                            pass
            # Синхронизируем folder_name — UI фильтрует таблицу аккаунтов по
            # этому полю. Без обновления мёртвый/замороженный акк продолжал
            # показываться во вкладке «В работе» хотя файлы уже переехали.
            if acc.folder_name != category:
                acc.folder_name = category

        if moved:
            logger.info("[accounts_folder] Moved %d files between categories", moved)

    except Exception as e:
        logger.debug("[accounts_folder] sync error: %s", e)
