import json
from io import BytesIO
from unittest.mock import patch
from django.test import SimpleTestCase, override_settings
from .sms import SMSDeliveryError, get_sms_balance, normalize_recipient, send_sms

class FakeResponse:
    def __init__(self, payload): self.body = BytesIO(json.dumps(payload).encode())
    def __enter__(self): return self
    def __exit__(self, *args): return False
    def read(self): return self.body.read()

@override_settings(ARKESEL_API_KEY="test-key", ARKESEL_SENDER_ID="HSM Alumni", ARKESEL_SMS_URL="https://sms.test/send", ARKESEL_BALANCE_URL="https://sms.test/balance", ARKESEL_TIMEOUT_SECONDS=3)
class ArkeselSMSTests(SimpleTestCase):
    def test_normalizes_e164_recipient(self):
        self.assertEqual(normalize_recipient("+233 24 000 0000"), "233240000000")

    @patch("apps.accounts.sms.urlopen")
    def test_send_sms_uses_v2_header_and_payload(self, urlopen):
        urlopen.return_value = FakeResponse({"status": "success", "data": [{"recipient": "233240000000", "id": "sms-id"}]})
        result = send_sms("+233240000000", "Test message")
        request = urlopen.call_args.args[0]
        self.assertEqual(request.get_header("Api-key"), "test-key")
        self.assertEqual(json.loads(request.data), {"sender": "HSM Alumni", "message": "Test message", "recipients": ["233240000000"]})
        self.assertEqual(result.message_id, "sms-id")

    @patch("apps.accounts.sms.urlopen")
    def test_balance_is_parsed(self, urlopen):
        urlopen.return_value = FakeResponse({"status": "success", "data": {"sms_balance": "25", "main_balance": "GHS 3.00"}})
        self.assertEqual(get_sms_balance(), {"sms_balance": "25", "main_balance": "GHS 3.00"})

    @patch("apps.accounts.sms.urlopen")
    def test_rejected_response_raises_delivery_error(self, urlopen):
        urlopen.return_value = FakeResponse({"status": "error", "message": "Insufficient balance"})
        with self.assertRaisesMessage(SMSDeliveryError, "Insufficient balance"):
            send_sms("+233240000000", "Test")
