# This file is part of Tryton.  The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.

import email.parser
import email.policy
import itertools
import re
from email.utils import getaddresses

import trytond.config as config
from trytond.i18n import gettext
from trytond.pool import PoolMeta
from trytond.transaction import Transaction

REPLY_LINE = '\N{EM DASH}' * 80
DESTINATION_RE = re.compile(r"^[^@]*\+([0-9a-f]{32})@", re.IGNORECASE)


def _get_channel_identifier(email):
    base = config.get(
        'inbound_email', 'chat_reply_to',
        default=config.get('email', 'from'))
    _, our_domain = base.split('@', 1)

    for key in ('To', 'Cc'):
        if key not in email:
            continue
        addresses = [a for _, a in getaddresses(email.get_all(key))]
        for address in addresses:
            _, domain = address.split('@', 1)
            if domain != our_domain:
                continue
            if (m := DESTINATION_RE.match(address)):
                channel_id, = m.groups()
                return channel_id
    return None


class Channel(metaclass=PoolMeta):
    __name__ = 'ir.chat.channel'

    @classmethod
    def _email_channel(cls, email):
        channel = super()._email_channel(email)
        channels = []
        if (channel_id := _get_channel_identifier(email)):
            channels = cls.search([('identifier', '=', channel_id)])
        return channel if len(channels) != 1 else channels[0]

    @classmethod
    def _email_content(cls, body):
        body = super()._email_content(body)
        return '\n'.join(itertools.takewhile(
                lambda l: REPLY_LINE not in l,
                body.splitlines()))

    @classmethod
    def post_inbound_email(cls, inbound_email, rule):
        parser = email.parser.BytesParser(policy=email.policy.default)
        message = parser.parsebytes(inbound_email.data)
        return cls.post_from_email(message)

    @classmethod
    def _email_reply_to(cls, message):
        reply_to = super()._email_reply_to(message)
        base = config.get(
            'inbound_email', 'chat_reply_to',
            default=reply_to or config.get('email', 'from'))
        local_part, domain_part = base.split('@', 1)
        if '+' in local_part:
            local_part, _ = local_part.split('+', 1)
        local_part += f'+{message.channel.identifier}'
        return '@'.join((local_part, domain_part))

    @classmethod
    def _email_body(cls, message):
        body = super()._email_body(message)
        with Transaction().set_context(language=message.channel.language):
            above_msg = gettext('inbound_email.msg_reply_above')
            return f'{REPLY_LINE}\n{above_msg}\n\n{body}'
