"""Tests for blocked channel senders in backup/restore."""

from types import SimpleNamespace
from unittest.mock import MagicMock, patch

from meshy.backup import BackupManager
from meshy.models import Channel


def _make_win(storage):
    win = MagicMock()
    win.storage = storage
    win._storage = storage
    win.channels = []
    win.contacts = []
    win.self_info = {}
    win.device_info = SimpleNamespace(
        name="",
        public_key="",
        radio_freq=0,
        radio_bw=0,
        radio_sf=0,
        radio_cr=0,
        tx_power=0,
        latitude=0,
        longitude=0,
    )
    win._device_info = win.device_info
    return win


class TestBackupBlockedSenders:
    def test_export_includes_blocked_senders(self, storage):
        win = _make_win(storage)
        win.channels = [Channel(index=0, name="General", psk=bytes(16))]
        storage.save_channel(win.channels[0])
        storage.block_channel_sender("Spammer")
        storage.block_channel_sender("Troll")

        mgr = BackupManager()
        backup = mgr.export_backup(win, sections={"messages"})

        assert "blocked_channel_senders" in backup
        assert sorted(backup["blocked_channel_senders"]) == ["Spammer", "Troll"]

    def test_export_omits_key_when_no_blocked(self, storage):
        win = _make_win(storage)
        win.channels = []

        mgr = BackupManager()
        backup = mgr.export_backup(win, sections={"messages"})

        assert "blocked_channel_senders" not in backup

    @patch("meshy.backup.GLib")
    def test_import_restores_blocked_senders(self, _mock_glib, storage):
        win = _make_win(storage)
        backup = {"blocked_channel_senders": ["Alice", "Bob"]}

        mgr = BackupManager()
        mgr._do_import_data(win, backup, {"messages"})

        assert storage.get_blocked_channel_senders() == {"Alice", "Bob"}

    @patch("meshy.backup.GLib")
    def test_import_updates_frame_handler_cache(self, _mock_glib, storage):
        win = _make_win(storage)
        backup = {"blocked_channel_senders": ["Spammer"]}

        mgr = BackupManager()
        mgr._do_import_data(win, backup, {"messages"})

        win._frame_handler.update_blocked_senders.assert_called_once()

    @patch("meshy.backup.GLib")
    def test_import_without_blocked_skips_cache_update(self, _mock_glib, storage):
        win = _make_win(storage)
        backup = {}

        mgr = BackupManager()
        mgr._do_import_data(win, backup, {"messages"})

        win._frame_handler.update_blocked_senders.assert_not_called()

    @patch("meshy.backup.GLib")
    def test_round_trip(self, _mock_glib, storage):
        win = _make_win(storage)
        win.channels = [Channel(index=0, name="General", psk=bytes(16))]
        storage.save_channel(win.channels[0])
        storage.block_channel_sender("Spammer")
        storage.block_channel_sender("Troll")

        mgr = BackupManager()
        backup = mgr.export_backup(win, sections={"messages"})

        storage.unblock_channel_sender("Spammer")
        storage.unblock_channel_sender("Troll")
        assert storage.get_blocked_channel_senders() == set()

        mgr._do_import_data(win, backup, {"messages"})

        assert storage.get_blocked_channel_senders() == {"Spammer", "Troll"}

    def test_available_sections_includes_messages_for_blocked(self):
        backup = {"blocked_channel_senders": ["Spammer"]}
        sections = BackupManager.available_sections(backup)
        assert "messages" in sections


class TestBackupRetention:
    def test_export_includes_retention_levels(self, storage):
        win = _make_win(storage)
        win.channels = [Channel(index=0, name="General", psk=bytes(16), retention_days=30)]
        storage.save_channel(win.channels[0])

        mgr = BackupManager()
        backup = mgr.export_backup(win, sections={"channels"})

        assert "retention_levels" in backup
        assert backup["retention_levels"] == {"0": 30}

    def test_export_omits_default_retention(self, storage):
        win = _make_win(storage)
        win.channels = [Channel(index=0, name="General", psk=bytes(16), retention_days=0)]
        storage.save_channel(win.channels[0])

        mgr = BackupManager()
        backup = mgr.export_backup(win, sections={"channels"})

        assert "retention_levels" not in backup

    @patch("meshy.backup.GLib")
    def test_import_restores_retention(self, _mock_glib, storage):
        win = _make_win(storage)
        storage.save_channel(Channel(index=0, name="General", psk=bytes(16)))
        backup = {"retention_levels": {"0": 7}}

        mgr = BackupManager()
        mgr._do_import_data(win, backup, {"channels"})

        ch = storage.get_channel(0)
        assert ch.retention_days == 7

    def test_available_sections_includes_channels_for_retention(self):
        backup = {"retention_levels": {"0": 30}}
        sections = BackupManager.available_sections(backup)
        assert "channels" in sections
