import requests

from django.utils.translation import ugettext_lazy as _
from django.db import models

from passerelle.utils.jsonresponse import APIError
from passerelle.base.models import BaseResource
from passerelle.sms import SMSGatewayMixin


class OVHSMSGateway(BaseResource, SMSGatewayMixin):
    URL = 'https://www.ovh.com/cgi-bin/sms/http2sms.cgi'
    MESSAGES_CLASSES = (
        (0, _('Message are directly shown to users on phone screen '
              'at reception. The message is never stored, neither in the '
              'phone memory nor in the SIM card. It is deleted as '
              'soon as the user validate the display.')),
        (1, _('Messages are stored in the phone memory, or in the '
              'SIM card if the memory is full. ')),
        (2, _('Messages are stored in the SIM card.')),
        (3, _('Messages are stored in external storage like a PDA or '
              'a PC.')),
    )
    account = models.CharField(max_length=64)
    username = models.CharField(max_length=64)
    password = models.CharField(max_length=64)
    msg_class = models.IntegerField(choices=MESSAGES_CLASSES, default=1,
                                    verbose_name=_('message class'))
    credit_threshold_alert = models.PositiveIntegerField(default=100)
    default_country_code = models.CharField(max_length=3, default=u'33')
    credit_left = models.PositiveIntegerField(default=0)
    # FIXME: add regexp field, to check destination and from format

    manager_view_template_name = 'passerelle/manage/messages_service_view.html'

    TEST_DEFAULTS = {
        'create_kwargs': {
            'account': '1234',
            'username': 'john',
            'password': 'doe',
        },
        'test_vectors': [
            {
                'response': '',
                'result': {
                    'err': 1,
                    'err_desc': 'OVH error: bad JSON response, \'\', '
                                'No JSON object could be decoded',
                }
            },
            {
                'response': {
                    'status': 100,
                    'creditLeft': 47,
                    'SmsIds': [1234],
                },
                'result': {
                    'err': 0,
                    'data': {
                        'credit_left': 47.0,
                        'ovh_result': {
                            'SmsIds': [1234],
                            'creditLeft': 47,
                            'status': 100
                        },
                        'sms_ids': [1234],
                        'warning': 'credit level too low for ovhsmsgateway: 47.0 (threshold 100)',
                    }
                }
            }

        ],

    }

    class Meta:
        verbose_name = 'OVH'
        db_table = 'sms_ovh'

    @classmethod
    def get_icon_class(cls):
        return 'phone'

    def send_msg(self, text, sender, destinations):
        """Send a SMS using the OVH provider"""
        # unfortunately it lacks a batch API...
        destinations = self.clean_numbers(destinations, self.default_country_code)

        text = unicode(text).encode('utf-8')
        to = ','.join(destinations)
        params = {
            'account': self.account.encode('utf-8'),
            'login': self.username.encode('utf-8'),
            'password': self.password.encode('utf-8'),
            'from': sender.encode('utf-8'),
            'to': to,
            'message': text,
            'contentType': 'text/json',
            'class': self.msg_class,
        }
        try:
            response = requests.post(self.URL, data=params)
        except requests.RequestException as e:
            raise APIError('OVH error: POST failed, %s' % e)
        else:
            try:
                result = response.json()
            except ValueError as e:
                raise APIError('OVH error: bad JSON response, %r, %s' % (response.content, e))
            else:
                if not isinstance(result, dict):
                    raise APIError('OVH error: bad JSON response %r, it should be a dictionnary' %
                                   result)
                if 100 <= result['status'] < 200:
                    ret = {}
                    credit_left = float(result['creditLeft'])
                    # update credit left
                    OVHSMSGateway.objects.filter(id=self.id).update(credit_left=credit_left)
                    if credit_left < self.credit_threshold_alert:
                        ret['warning'] = ('credit level too low for %s: %s (threshold %s)' %
                                          (self.slug, credit_left, self.credit_threshold_alert))
                    ret['credit_left'] = credit_left
                    ret['ovh_result'] = result
                    ret['sms_ids'] = result.get('SmsIds', [])
                    return ret
                else:
                    raise APIError('OVH error: %r' % result)
