import re

from odoo import http
from odoo.http import request


class TierSendNotificationController(http.Controller):
    """RPC endpoint for sending a message through an external channel.

    Called from JS after message_post succeeds.
    Returns a status dict that JS uses to show a toast notification.
    """

    @http.route(
        '/tier_communications/send_via_channel',
        methods=['POST'],
        type='jsonrpc',
        auth='user',
    )
    def send_via_channel(self, message_id, channel_code, thread_model=None, thread_id=None):
        """Send an already-created mail.message through the specified external channel.

        Returns:
            {
                'status': 'success' | 'error' | 'no_data',
                'message': str,   # human-readable status for the toast
            }
        """
        message = request.env['mail.message'].browse(message_id)
        if not message.exists():
            return {'status': 'error', 'message': 'Сообщение не найдено'}

        if channel_code == 'email':
            return _send_email(request.env, message, thread_model, thread_id)
        elif channel_code == 'matrix':
            return _send_matrix(request.env, message)
        else:
            return {'status': 'error', 'message': f'Неизвестный канал: {channel_code}'}


def _send_email(env, message, thread_model, thread_id):
    """Send message via email. Returns status dict."""
    recipient_email = None

    # 1. Thread partner_id
    if thread_model and thread_id and thread_model not in ('mail.thread', 'discuss.channel'):
        thread_record = env[thread_model].browse(thread_id)
        if thread_record.exists() and hasattr(thread_record, 'partner_id'):
            partner = thread_record.partner_id
            if partner and partner.email:
                recipient_email = partner.email

    # 2. Message partner_ids
    if not recipient_email and message.partner_ids:
        for partner in message.partner_ids:
            if partner.email:
                recipient_email = partner.email
                break

    # 3. Last incoming message email_from
    if not recipient_email and message.model and message.res_id:
        last_incoming = env['mail.message'].search([
            ('model', '=', message.model),
            ('res_id', '=', message.res_id),
            ('message_type', 'in', ['email', 'comment']),
            ('email_from', '!=', False),
            ('author_id', '!=', 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. discuss.channel other member
    if not recipient_email and thread_model == 'discuss.channel' and thread_id:
        channel = env['discuss.channel'].browse(thread_id)
        if channel.exists():
            other_members = channel.channel_member_ids.filtered(
                lambda m: m.partner_id and m.partner_id != 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:
        return {
            'status': 'no_data',
            'message': 'Не заполнен email получателя',
        }

    try:
        mail_values = {
            'subject': message.subject or 'Сообщение из Odoo',
            'body_html': message.body or '',
            'email_to': recipient_email,
            'email_from': env.company.email or env.user.email or '',
            'auto_delete': True,
        }
        outgoing_mail = env['mail.mail'].sudo().create(mail_values)
        outgoing_mail.send()
        return {
            'status': 'success',
            'message': f'Сообщение отправлено на {recipient_email}',
        }
    except Exception as send_error:
        return {
            'status': 'error',
            'message': f'Ошибка отправки email: {send_error}',
        }


def _send_matrix(env, message):
    """Send message via Matrix. Returns status dict."""
    current_user = env.user

    if not hasattr(current_user, 'tier_matrix_homeserver'):
        return {
            'status': 'no_data',
            'message': 'Модуль Matrix не установлен',
        }

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

    missing_fields = []
    if not homeserver_url:
        missing_fields.append('Homeserver URL')
    if not access_token:
        missing_fields.append('Access Token')
    if not room_id:
        missing_fields.append('Room ID')

    if missing_fields:
        return {
            'status': 'no_data',
            'message': f'Не заполнены данные Matrix: {", ".join(missing_fields)}',
        }

    if 'tier.channel.matrix.helper' not in env:
        return {
            'status': 'no_data',
            'message': 'Модуль Matrix не установлен',
        }

    try:
        env['tier.channel.matrix.helper'].channel_send_message(message, user=current_user)
        return {
            'status': 'success',
            'message': f'Сообщение отправлено в Matrix (room: {room_id})',
        }
    except Exception as send_error:
        return {
            'status': 'error',
            'message': f'Ошибка отправки Matrix: {send_error}',
        }
