"""
account_state.py — персистентность статусов аккаунтов между запусками.

Хранит {phone: {dead, frozen, spam_blocked, ...}} в data/account_states.json.
Раньше статусы (acc.dead/frozen/spam_blocked) жили только в памяти + косвенно
в папке хранения файла. При перезапуске:
  - если sync_accounts_folder не успел переместить файл (file-lock, антивирус) —
    автоload видел файл в исходной папке «В работе» и сбрасывал статус в False.
  - если файл лежал в «После инвайта/Заморозка/» (parent.name == "Заморозка"),
    автоload по совпадению ставил frozen=True, но это было хрупко.

Этот модуль — независимый источник истины: записываем при ЛЮБОМ изменении
статуса (check_spam, invite-retire, ensure_connected), читаем при autoload.
"""
import json
import logging
import threading
from pathlib import Path
from typing import Dict, Any

logger = logging.getLogger("telepush.account_state")

# Простой файловый стор — в data/. Для выживания обновлений ещё дублируем
# в ~/.telepush/account_states.json (как user_settings.json).
_LOCK = threading.RLock()


def _state_file() -> Path:
    from config import DATA_DIR
    return DATA_DIR / "account_states.json"


def _backup_file() -> Path:
    return Path.home() / ".telepush" / "account_states.json"


def load_states() -> Dict[str, Dict[str, Any]]:
    """Загружает текущие статусы. Если data/ пустая — читает из ~/.telepush/."""
    paths = [_state_file(), _backup_file()]
    for p in paths:
        try:
            if p.exists():
                with _LOCK:
                    data = json.loads(p.read_text(encoding="utf-8"))
                if isinstance(data, dict):
                    return data
        except Exception as e:
            logger.warning("[account_state] не смог прочитать %s: %s", p, e)
    return {}


def _save_atomic(states: Dict[str, Dict[str, Any]]) -> bool:
    """Атомарная запись (через temp + rename), и зеркало в ~/.telepush/."""
    p = _state_file()
    try:
        p.parent.mkdir(parents=True, exist_ok=True)
        tmp = p.with_suffix(".tmp")
        tmp.write_text(json.dumps(states, ensure_ascii=False, indent=2), encoding="utf-8")
        tmp.replace(p)
    except Exception as e:
        logger.warning("[account_state] не смог записать %s: %s", p, e)
        return False
    # Зеркало в ~/.telepush/ — переживает удаление data/.
    try:
        bp = _backup_file()
        bp.parent.mkdir(parents=True, exist_ok=True)
        bp.write_text(json.dumps(states, ensure_ascii=False, indent=2), encoding="utf-8")
    except Exception:
        pass
    return True


def save_account_state(phone: str, **fields):
    """Обновляет статус одного аккаунта. Только переданные поля. Поддерживает:
    dead, dead_reason, frozen, frozen_reason, spam_blocked, spam_block_note,
    spam_permanent, last_status_change_ts.
    """
    if not phone:
        return
    with _LOCK:
        states = load_states()
        cur = states.get(phone) or {}
        cur.update({k: v for k, v in fields.items() if v is not None})
        # Авто-timestamp последнего изменения — полезно для отладки/UI.
        try:
            import time as _t
            cur["last_status_change_ts"] = int(_t.time())
        except Exception:
            pass
        states[phone] = cur
        _save_atomic(states)


def clear_account_state(phone: str):
    """Удаляет статус — при удалении акка."""
    if not phone:
        return
    with _LOCK:
        states = load_states()
        if phone in states:
            del states[phone]
            _save_atomic(states)


def apply_state_to_account(acc) -> bool:
    """Восстанавливает статусы в Account из persistent store.
    Возвращает True если что-то восстановилось."""
    phone = getattr(acc, "phone", None)
    if not phone:
        return False
    states = load_states()
    st = states.get(phone)
    if not st:
        return False
    applied = False
    if st.get("dead"):
        acc.dead = True
        acc.dead_reason = st.get("dead_reason") or getattr(acc, "dead_reason", "") or "from_state"
        applied = True
    if st.get("frozen"):
        acc.frozen = True
        acc.frozen_reason = st.get("frozen_reason") or getattr(acc, "frozen_reason", "") or "from_state"
        applied = True
    if st.get("spam_blocked"):
        acc.spam_blocked = True
        if st.get("spam_block_note"):
            acc.spam_block_note = st["spam_block_note"]
        if st.get("spam_permanent"):
            acc.spam_permanent = True
        applied = True
    return applied
