# passerelle - uniform access to multiple data sources and services
# Copyright (C) 2020  Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
import requests
from django.db import models
from django.utils.translation import gettext_lazy as _
from requests.auth import HTTPBasicAuth

from passerelle.sms.models import SMSResource
from passerelle.utils.jsonresponse import APIError


class TwilioSMSGateway(SMSResource):
    hide_description_fields = ['account_sid']

    account_sid = models.CharField(verbose_name=_('Account Sid'), max_length=64)
    auth_token = models.CharField(verbose_name=_('Auth Token'), max_length=64)

    class Meta:
        verbose_name = 'Twilio'
        db_table = 'sms_twilio'

    TEST_DEFAULTS = {
        'create_kwargs': {
            'account_sid': 'ACxxx',
            'auth_token': 'yyy',
        },
        'test_vectors': [
            {
                'status_code': 400,
                'response': 'my error message',
                'result': {
                    'err': 1,
                    'err_desc': 'Twilio error: some destinations failed',
                    'data': [
                        ['+33688888888', "Twilio error: my error message"],
                        ['+33677777777', "Twilio error: my error message"],
                    ],
                },
            },
            {
                'status_code': 201,
                'result': {
                    'err': 0,
                    'data': None,
                },
            },
        ],
    }
    URL = 'https://api.twilio.com/2010-04-01/Accounts'

    def send_msg(self, text, sender, destinations, **kwargs):
        """Send a SMS using the Twilio provider"""
        # from https://www.twilio.com/docs/usage/requests-to-twilio

        # set destinations phone number in E.164 format
        # [+][country code][phone number including area code]
        numbers = []
        for dest in destinations:
            numbers.append('+' + dest[2:])
        destinations = numbers

        url = '%s/%s/Messages.json' % (TwilioSMSGateway.URL, self.account_sid)
        auth = HTTPBasicAuth(self.account_sid, self.auth_token)
        results = []
        for dest in destinations:
            params = {'Body': text, 'From': sender, 'To': dest}
            try:
                resp = self.requests.post(url, params, auth=auth)
            except requests.RequestException as exc:
                raise APIError('Twilio error: POST failed, %s' % exc)
            else:
                if resp.status_code != 201:
                    results.append('Twilio error: %s' % resp.text)
                else:
                    results.append(0)
        if any(results):
            raise APIError('Twilio error: some destinations failed', data=list(zip(destinations, results)))
        # credit consumed is unknown
