import abc
from django.conf import settings
from django.utils import timezone
from .models import OutboundSms


class BaseSmsBackend(abc.ABC):
    @abc.abstractmethod
    def send(self, sms: OutboundSms) -> bool: ...


class TwilioBackend(BaseSmsBackend):
    def send(self, sms):
        try:
            from twilio.rest import Client
        except ImportError:
            sms.status, sms.error = OutboundSms.FAILED, "pip install twilio"
            sms.save(update_fields=["status", "error"]); return False
        try:
            client = Client(settings.TWILIO_ACCOUNT_SID, settings.TWILIO_AUTH_TOKEN)
            msg = client.messages.create(to=sms.to_number, from_=settings.TWILIO_FROM_NUMBER, body=sms.body)
            sms.provider_sid, sms.status, sms.sent_at = msg.sid, OutboundSms.SENT, timezone.now()
            sms.attempts += 1
            sms.save(update_fields=["provider_sid", "status", "sent_at", "attempts"]); return True
        except Exception as e:
            sms.status, sms.error = OutboundSms.FAILED, str(e)[:500]; sms.attempts += 1
            sms.save(update_fields=["status", "error", "attempts"]); return False


class OwnSimBackend(BaseSmsBackend):
    # Leaves it QUEUED; the Android gateway pulls it via /api/sms/pending.
    def send(self, sms):
        sms.status = OutboundSms.QUEUED
        sms.save(update_fields=["status"]); return True


def get_backend():
    return TwilioBackend() if settings.SMS_BACKEND == "twilio" else OwnSimBackend()


def enqueue_sms(to_number, body, organization=None, event=None):
    sms = OutboundSms.objects.create(to_number=to_number, body=body,
                                     organization=organization, event=event,
                                     backend=settings.SMS_BACKEND)
    get_backend().send(sms)   # twilio sends immediately; ownsim just queues
    return sms