# retoor <retoor@molodetz.nl>

from devplacepy.services.telegram.backend import FakeTelegramBackend
from devplacepy.services.telegram.worker import TelegramWorker
from tests.conftest import run_async


def _run(coro):
    return run_async(coro)


def _worker(backend):
    frames = []

    async def emit(frame):
        frames.append(frame)

    return TelegramWorker(backend, emit), frames


def test_private_text_message_emitted():
    backend = FakeTelegramBackend()
    worker, frames = _worker(backend)
    _run(
        worker.process_update(
            {
                "update_id": 1,
                "message": {
                    "chat": {"id": 42, "type": "private"},
                    "from": {"id": 7},
                    "text": "hello",
                },
            }
        )
    )
    messages = [f for f in frames if f["type"] == "message"]
    assert len(messages) == 1
    assert messages[0]["chat_id"] == 42 and messages[0]["text"] == "hello"


def test_callback_query_emitted():
    backend = FakeTelegramBackend()
    worker, frames = _worker(backend)
    _run(
        worker.process_update(
            {
                "update_id": 2,
                "callback_query": {
                    "id": "cb1",
                    "from": {"id": 7},
                    "data": "i=del1;k=env;v=stg",
                    "message": {
                        "message_id": 9,
                        "chat": {"id": 42, "type": "private"},
                    },
                },
            }
        )
    )
    callbacks = [f for f in frames if f["type"] == "callback"]
    assert len(callbacks) == 1
    assert callbacks[0]["chat_id"] == 42
    assert callbacks[0]["data"] == "i=del1;k=env;v=stg"
    assert callbacks[0]["callback_query_id"] == "cb1"


def test_group_message_ignored():
    backend = FakeTelegramBackend()
    worker, frames = _worker(backend)
    _run(
        worker.process_update(
            {
                "update_id": 1,
                "message": {
                    "chat": {"id": 9, "type": "group"},
                    "from": {"id": 7},
                    "text": "x",
                },
            }
        )
    )
    assert not [f for f in frames if f["type"] == "message"]


def test_photo_becomes_data_uri():
    backend = FakeTelegramBackend()
    backend.files["abc"] = b"\xff\xd8\xff" + b"0" * 50
    worker, frames = _worker(backend)
    _run(
        worker.process_update(
            {
                "update_id": 1,
                "message": {
                    "chat": {"id": 42, "type": "private"},
                    "from": {"id": 7},
                    "photo": [{"file_id": "abc", "file_size": 53}],
                },
            }
        )
    )
    message = [f for f in frames if f["type"] == "message"][0]
    assert message["images"][0].startswith("data:image/jpeg;base64,")


def test_html_send_falls_back_to_plain_on_entity_error():
    class EntityBackend(FakeTelegramBackend):
        async def send_message(self, chat_id, text, parse_mode, reply_markup=None):
            if parse_mode:
                return {
                    "ok": False,
                    "error_code": 400,
                    "description": "Bad Request: can't parse entities",
                }
            return await super().send_message(chat_id, text, None, reply_markup=reply_markup)

    backend = EntityBackend()
    worker, frames = _worker(backend)
    _run(
        worker.handle_command(
            {"cmd": "send", "req_id": "r1", "chat_id": 42, "text": "<b>x</b>", "parse_mode": "HTML"}
        )
    )
    assert backend.sent[-1]["parse_mode"] is None
    result = [f for f in frames if f["type"] == "result"][0]
    assert result["ok"] and result["req_id"] == "r1"
