# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

import random
import string

from odoo import api, fields, models
from odoo.osv import expression


class MailingTrace(models.Model):
    """ Improve statistics model to add SMS support. Main attributes of
    statistics model are used, only some specific data is required. """
    _inherit = 'mailing.trace'
    CODE_SIZE = 3

    trace_type = fields.Selection(selection_add=[
        ('sms', 'SMS')
    ], ondelete={'sms': 'set default'})
    sms_sms_id = fields.Many2one('sms.sms', string='SMS', index=True, ondelete='set null')
    sms_sms_id_int = fields.Integer(
        string='SMS ID (tech)',
        help='ID of the related sms.sms. This field is an integer field because '
             'the related sms.sms can be deleted separately from its statistics. '
             'However the ID is needed for several action and controllers.',
        index=True,
    )
    sms_number = fields.Char('Number')
    sms_code = fields.Char('Code')
    failure_type = fields.Selection(selection_add=[
        ('sms_number_missing', 'Missing Number'),
        ('sms_number_format', 'Wrong Number Format'),
        ('sms_credit', 'Insufficient Credit'),
        ('sms_server', 'Server Error'),
        ('sms_acc', 'Unregistered Account'),
        # mass mode specific codes
        ('sms_blacklist', 'Blacklisted'),
        ('sms_duplicate', 'Duplicate'),
    ])

    @api.model_create_multi
    def create(self, values_list):
        for values in values_list:
            if 'sms_sms_id' in values:
                values['sms_sms_id_int'] = values['sms_sms_id']
            if values.get('trace_type') == 'sms' and not values.get('sms_code'):
                values['sms_code'] = self._get_random_code()
        return super(MailingTrace, self).create(values_list)

    def _get_random_code(self):
        """ Generate a random code for trace. Uniqueness is not really necessary
        as it serves as obfuscation when unsubscribing. A valid trio
        code / mailing_id / number will be requested. """
        return ''.join(random.choice(string.ascii_letters + string.digits) for dummy in range(self.CODE_SIZE))

    def _get_records_from_sms(self, sms_sms_ids=None, additional_domain=None):
        if not self.ids and sms_sms_ids:
            domain = [('sms_sms_id_int', 'in', sms_sms_ids)]
        else:
            domain = [('id', 'in', self.ids)]
        if additional_domain:
            domain = expression.AND([domain, additional_domain])
        return self.search(domain)

    def set_failed(self, failure_type):
        for trace in self:
            trace.write({'exception': fields.Datetime.now(), 'failure_type': failure_type})

    def set_sms_sent(self, sms_sms_ids=None):
        statistics = self._get_records_from_sms(sms_sms_ids, [('sent', '=', False)])
        statistics.write({'sent': fields.Datetime.now()})
        return statistics

    def set_sms_clicked(self, sms_sms_ids=None):
        statistics = self._get_records_from_sms(sms_sms_ids, [('clicked', '=', False)])
        statistics.write({'clicked': fields.Datetime.now()})
        return statistics

    def set_sms_ignored(self, sms_sms_ids=None):
        statistics = self._get_records_from_sms(sms_sms_ids, [('ignored', '=', False)])
        statistics.write({'ignored': fields.Datetime.now()})
        return statistics

    def set_sms_exception(self, sms_sms_ids=None):
        statistics = self._get_records_from_sms(sms_sms_ids, [('exception', '=', False)])
        statistics.write({'exception': fields.Datetime.now()})
        return statistics
