"""
Envio de SMS.

La vista anterior instanciaba `TwilioUtil`, recorria los numeros y llamaba al
proveedor dentro de la peticion HTTP. Con veinte destinatarios eran veinte
llamadas de red seguidas, y si una fallaba a la mitad, el `except:` desnudo
devolvia `400 Invalid data` sin decir cuales se habian enviado ya. El cliente
no tenia forma de saber si reintentar duplicaria mensajes.

Ahora cada numero es una fila de auditoria con su propio identificador y su
propio estado, y el envio se encola.
"""

from __future__ import annotations

import logging

from drf_spectacular.utils import extend_schema
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView

from core.authentications.token_auth import TokenAuthentication
from core.permissions import HasScope
from keys.models.api_keys import SCOPE_SMS_SEND
from notifications.controllers.v1.mail.conversation import _error
from notifications.models.message import Channel
from notifications.serializers.sms import SMSSendSerializer
from notifications.services.messenger import send_many
from notifications.services.results import resumen_de_envios
from notifications.throttling import SendThrottle

logger = logging.getLogger("notifications.sms")


class Send(APIView):
    """Envia un SMS a cada numero de la lista."""

    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated, HasScope]
    required_scope = SCOPE_SMS_SEND
    throttle_classes = [SendThrottle]

    @extend_schema(
        summary="Enviar SMS",
        request=SMSSendSerializer,
        responses={200: None, 202: None, 207: None, 400: None, 503: None},
    )
    def post(self, request, format=None):
        serializer = SMSSendSerializer(data=request.data, context={"request": request})
        serializer.is_valid(raise_exception=True)
        datos = serializer.validated_data

        from notifications.channels.messaging.registry import (
            UnknownProvider,
            get_provider,
        )

        try:
            provider = get_provider()
        except UnknownProvider as exc:
            return _error(
                request,
                "provider_unavailable",
                str(exc),
                status.HTTP_503_SERVICE_UNAVAILABLE,
            )

        mensajes = send_many(
            channel=Channel.SMS,
            numbers=datos["to"],
            body=datos["body"],
            provider_name=provider.name,
            send_async=datos.get("send_async", True),
            request=request,
            api_key=getattr(request, "api_key_record", None),
        )

        return resumen_de_envios(request, mensajes, Channel.SMS)
