from __future__ import annotations

from unittest.mock import patch

from asgiref.sync import async_to_sync
from django.test import TestCase

from core.clients import signalapi


class _FakeResponse:
    def __init__(self, status_code: int, body: str):
        self.status = int(status_code)
        self._body = str(body)

    async def __aenter__(self):
        return self

    async def __aexit__(self, exc_type, exc, tb):
        return False

    async def text(self):
        return self._body


class _FakeClientSession:
    posted_payloads: list[dict] = []
    next_status = 400
    next_body = "invalid recipient"

    def __init__(self, *args, **kwargs):
        pass

    async def __aenter__(self):
        return self

    async def __aexit__(self, exc_type, exc, tb):
        return False

    def post(self, url, json=None):
        self.__class__.posted_payloads.append(dict(json or {}))
        return _FakeResponse(self.__class__.next_status, self.__class__.next_body)


class SignalSendNormalizationTests(TestCase):
    def test_normalize_signal_recipient_phone_and_uuid(self):
        self.assertEqual(
            "+447700900000", signalapi.normalize_signal_recipient("447700900000")
        )
        self.assertEqual(
            "+447700900000", signalapi.normalize_signal_recipient("+44 7700-900000")
        )
        uuid_value = "756078fd-d447-426d-a620-581a86d64f51"
        self.assertEqual(uuid_value, signalapi.normalize_signal_recipient(uuid_value))

    def test_send_message_raw_returns_detailed_error_with_normalized_recipient(self):
        _FakeClientSession.posted_payloads = []
        _FakeClientSession.next_status = 400
        _FakeClientSession.next_body = "invalid recipient format"
        with patch("core.clients.signalapi.aiohttp.ClientSession", _FakeClientSession):
            result = async_to_sync(signalapi.send_message_raw)(
                recipient_uuid="447700900000",
                text="hello",
                attachments=[],
                metadata={},
                detailed=True,
            )

        self.assertIsInstance(result, dict)
        self.assertFalse(bool(result.get("ok")))
        self.assertEqual(400, int(result.get("status") or 0))
        self.assertEqual("+447700900000", str(result.get("recipient") or ""))
        self.assertIn("invalid recipient", str(result.get("error") or ""))
        self.assertGreaterEqual(len(_FakeClientSession.posted_payloads), 1)
        first_payload = _FakeClientSession.posted_payloads[0]
        self.assertEqual(["+447700900000"], first_payload.get("recipients"))
