import logging
import re

from odoo import models

_logger = logging.getLogger(__name__)


class MailThread(models.AbstractModel):
    _inherit = 'mail.thread'

    def _get_allowed_message_params(self):
        """Extend allowed params so channel_tag_ids passes through the controller."""
        return super()._get_allowed_message_params() | {'channel_tag_ids'}

    def _get_message_create_valid_field_names(self):
        """Add channel_tag_ids to the whitelist for _message_create."""
        return super()._get_message_create_valid_field_names() | {'channel_tag_ids'}

    def assign_mailbox(self, mailbox_id):
        """Assign all messages of this thread to the given tier.mailbox.

        Called from the chatter UI when user clicks "Входящие лиды" / "Входящие тикеты".
        Removes existing tags for this mailbox first to avoid duplicates.
        """
        self.ensure_one()
        mailbox = self.env['tier.mailbox'].browse(mailbox_id)
        if not mailbox.exists():
            return False

        # Get all messages of this thread
        thread_messages = self.env['mail.message'].search([
            ('model', '=', self._name),
            ('res_id', '=', self.id),
        ])

        for message in thread_messages:
            # Remove existing tag for this mailbox if any
            existing_tag = message.mailbox_tag_ids.filtered(
                lambda tag: tag.mailbox_id.id == mailbox_id
            )
            if existing_tag:
                existing_tag.unlink()
            # Create new tag
            self.env['tier.mailbox.tag'].create({
                'mailbox_id': mailbox_id,
                'message_id': message.id,
            })

        print(
            f"[tier_communications] assign_mailbox: "
            f"thread {self._name}#{self.id} → mailbox '{mailbox.name}' "
            f"({len(thread_messages)} messages tagged)"
        )
        return True

    # =========================================================================
    # ОТПРАВКА ИСХОДЯЩИХ СООБЩЕНИЙ
    # =========================================================================

    def message_post(self, *, body='', **kwargs):
        """Override: создаём сообщение в Odoo. Внешняя отправка через канал
        выполняется отдельным RPC-вызовом из JS (/tier_communications/send_via_channel).
        """
        message = super().message_post(body=body, **kwargs)
        if not message:
            return message

        if not message.channel_tag_ids:
            print(
                f"[tier_communications] message_post: msg_id={message.id} — "
                f"канал не выбран, сообщение только в Odoo"
            )

        return message

    # =========================================================================
    # ! ОТПРАВКА СООБЩЕНИЯ НА EMAIL
    # =========================================================================

    def _tier_send_email(self, message):
        """Отправить сообщение на email партнёра треда через стандартный mail.mail."""
        recipient_email = None

        # 1. Thread has partner_id (business models: sale.order, crm.lead, etc.)
        if self._name not in ('mail.thread', 'discuss.channel') and hasattr(self, 'partner_id'):
            partner = self.partner_id
            if partner and partner.email:
                recipient_email = partner.email

        # 2. Message has explicit partner_ids
        if not recipient_email and message.partner_ids:
            for partner in message.partner_ids:
                partner_email = partner.email if hasattr(partner, 'email') else None
                if partner_email and isinstance(partner_email, str) and '@' in partner_email:
                    recipient_email = partner_email
                    break

        # 3. Last incoming message in this thread — use its email_from
        if not recipient_email and message.model and message.res_id:
            last_incoming = self.env['mail.message'].search([
                ('model', '=', message.model),
                ('res_id', '=', message.res_id),
                ('message_type', 'in', ['email', 'comment']),
                ('email_from', '!=', False),
                ('author_id', '!=', self.env.user.partner_id.id),
            ], order='id desc', limit=1)
            if last_incoming and last_incoming.email_from:
                email_match = re.search(r'<([^>]+)>', last_incoming.email_from)
                recipient_email = email_match.group(1) if email_match else last_incoming.email_from

        # 4. For discuss.channel — find the other member's email
        if not recipient_email and self._name == 'discuss.channel':
            other_members = self.channel_member_ids.filtered(
                lambda m: m.partner_id and m.partner_id != self.env.user.partner_id
            )
            for member in other_members:
                if member.partner_id.email:
                    recipient_email = member.partner_id.email
                    break

        if not recipient_email:
            print(
                f"[tier_communications] ! ОТПРАВКА СООБЩЕНИЯ НА EMAIL: "
                f"msg_id={message.id} — У пользователя нет email адреса получателя"
            )
            return

        print(
            f"[tier_communications] ! ОТПРАВКА СООБЩЕНИЯ НА EMAIL: "
            f"msg_id={message.id}, email_to={recipient_email}"
        )

        try:
            mail_values = {
                'subject': message.subject or 'Сообщение из Odoo',
                'body_html': message.body or '',
                'email_to': recipient_email,
                'email_from': self.env.company.email or self.env.user.email or '',
                'auto_delete': True,
            }
            outgoing_mail = self.env['mail.mail'].sudo().create(mail_values)
            outgoing_mail.send()
            print(
                f"[tier_communications] ! ОТПРАВКА СООБЩЕНИЯ НА EMAIL: "
                f"msg_id={message.id} — SUCCESS, mail.mail id={outgoing_mail.id}"
            )
        except Exception as send_error:
            print(
                f"[tier_communications] ! ОТПРАВКА СООБЩЕНИЯ НА EMAIL: "
                f"msg_id={message.id} — ОШИБКА: {send_error}"
            )
            _logger.exception(
                'tier_communications: ошибка отправки email, msg_id=%s', message.id
            )

    # =========================================================================
    # ! ОТПРАВКА СООБЩЕНИЯ НА MATRIX
    # =========================================================================

    def _tier_send_matrix(self, message):
        """Отправить сообщение в Matrix комнату текущего пользователя."""
        current_user = self.env.user

        # Matrix fields are defined in tier_communications_matrix module
        # If not installed — fields don't exist
        if not hasattr(current_user, 'tier_matrix_homeserver'):
            print(
                f"[tier_communications] ! ОТПРАВКА СООБЩЕНИЯ НА MATRIX: "
                f"msg_id={message.id} — модуль tier_communications_matrix не установлен"
            )
            return

        homeserver_url = current_user.tier_matrix_homeserver
        access_token = current_user.tier_matrix_access_token
        room_id = current_user.tier_matrix_room_id

        if not homeserver_url:
            print(
                f"[tier_communications] ! ОТПРАВКА СООБЩЕНИЯ НА MATRIX: "
                f"msg_id={message.id} — У пользователя нет homeserver URL (tier_matrix_homeserver)"
            )
            return
        if not access_token:
            print(
                f"[tier_communications] ! ОТПРАВКА СООБЩЕНИЯ НА MATRIX: "
                f"msg_id={message.id} — У пользователя нет access token (tier_matrix_access_token)"
            )
            return
        if not room_id:
            print(
                f"[tier_communications] ! ОТПРАВКА СООБЩЕНИЯ НА MATRIX: "
                f"msg_id={message.id} — У пользователя нет room ID (tier_matrix_room_id)"
            )
            return

        print(
            f"[tier_communications] ! ОТПРАВКА СООБЩЕНИЯ НА MATRIX: "
            f"msg_id={message.id}, room={room_id}, homeserver={homeserver_url}"
        )

        if 'tier.channel.matrix.helper' in self.env:
            try:
                self.env['tier.channel.matrix.helper'].channel_send_message(
                    message, user=current_user
                )
            except Exception as send_error:
                print(
                    f"[tier_communications] ! ОТПРАВКА СООБЩЕНИЯ НА MATRIX: "
                    f"msg_id={message.id} — ОШИБКА: {send_error}"
                )
                _logger.exception(
                    'tier_communications: ошибка отправки matrix, msg_id=%s', message.id
                )
        else:
            print(
                f"[tier_communications] ! ОТПРАВКА СООБЩЕНИЯ НА MATRIX: "
                f"msg_id={message.id} — модуль tier_communications_matrix не установлен"
            )

    # =========================================================================
    # ПРИЁМ ВХОДЯЩИХ СООБЩЕНИЙ (fetchmail / стандартный механизм Odoo)
    # =========================================================================

    def message_process(self, model, message, custom_values=None, save_original=False,
                        strip_attachments=False, thread_id=None):
        """Override: после стандартной обработки входящего письма — помечаем тегом email."""
        result = super().message_process(
            model, message,
            custom_values=custom_values,
            save_original=save_original,
            strip_attachments=strip_attachments,
            thread_id=thread_id,
        )
        if result:
            incoming_message = self.env['mail.message'].search(
                [('model', '=', model), ('res_id', '=', result)],
                order='id desc',
                limit=1,
            )
            if incoming_message:
                email_tag = self.env['tier.channel.tag'].search(
                    [('code', '=', 'email')], limit=1
                )
                if email_tag and not incoming_message.channel_tag_ids:
                    incoming_message.channel_tag_ids = [(4, email_tag.id)]
                    print(
                        f"[tier_communications] message_process: "
                        f"входящее письмо msg_id={incoming_message.id} помечено тегом 'email'"
                    )
                from .tier_router import TierRouter
                TierRouter(self.env).route_incoming(incoming_message)
        return result
