import uuid
import logging
import requests
from odoo import _, models
from odoo.exceptions import UserError

_logger = logging.getLogger(__name__)


class TierChannelMatrixHelper(models.AbstractModel):
    """Helper for Matrix channel operations using per-user credentials from res.users.

    Credentials stored on res.users: tier_matrix_homeserver, tier_matrix_access_token, tier_matrix_room_id.
    """
    _name = 'tier.channel.matrix.helper'
    _description = 'Matrix Channel Helper'

    def _get_user_matrix_config(self, user=None):
        if not user:
            user = self.env.user
        return {
            'homeserver_url': user.tier_matrix_homeserver,
            'access_token': user.tier_matrix_access_token,
            'room_id': user.tier_matrix_room_id,
        }

    def channel_authenticate(self, user=None):
        """Verify Matrix credentials for the given user."""
        config = self._get_user_matrix_config(user)
        if not all([config['homeserver_url'], config['access_token']]):
            raise UserError(_('Matrix credentials not configured for this user.'))

        url = f"{config['homeserver_url'].rstrip('/')}/_matrix/client/v3/account/whoami"
        headers = {'Authorization': f"Bearer {config['access_token']}"}
        try:
            resp = requests.get(url, headers=headers, timeout=10)
            if resp.status_code == 200:
                return True
            raise UserError(
                _('Matrix authentication failed (HTTP %s): %s') % (resp.status_code, resp.text)
            )
        except requests.exceptions.RequestException as e:
            raise UserError(_('Cannot connect to Matrix homeserver: %s') % str(e))

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

    def channel_send_message(self, message, user=None):
        """Send a mail.message to Matrix using user's credentials."""
        if not user:
            user = self.env.user

        config = self._get_user_matrix_config(user)

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

        txn_id = str(uuid.uuid4())
        url = (
            f"{config['homeserver_url'].rstrip('/')}/_matrix/client/v3/rooms/"
            f"{config['room_id']}/send/m.room.message/{txn_id}"
        )
        headers = {
            'Authorization': f"Bearer {config['access_token']}",
            'Content-Type': 'application/json',
        }
        # Убираем HTML теги для Matrix (plain text)
        import re
        body_text = re.sub(r'<[^>]+>', '', message.body or '')

        payload = {
            'msgtype': 'm.text',
            'body': body_text,
            'format': 'org.matrix.custom.html',
            'formatted_body': message.body or '',
        }

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

        try:
            resp = requests.put(url, json=payload, headers=headers, timeout=15)
            if resp.status_code not in (200, 201):
                print(
                    f"[tier_matrix] ! ОТПРАВКА СООБЩЕНИЯ НА MATRIX: "
                    f"msg_id={message.id} — HTTP {resp.status_code}: {resp.text}"
                )
                raise UserError(
                    _('Failed to send Matrix message (HTTP %s): %s') % (resp.status_code, resp.text)
                )
            event_id = resp.json().get('event_id', '')
            print(
                f"[tier_matrix] ! ОТПРАВКА СООБЩЕНИЯ НА MATRIX: "
                f"msg_id={message.id} — SUCCESS, event_id={event_id}"
            )
        except requests.exceptions.RequestException as e:
            print(
                f"[tier_matrix] ! ОТПРАВКА СООБЩЕНИЯ НА MATRIX: "
                f"msg_id={message.id} — ОШИБКА соединения: {e}"
            )
            raise UserError(_('Matrix send error: %s') % str(e))

    # =========================================================================
    # ПРИЁМ ВХОДЯЩЕГО СООБЩЕНИЯ ИЗ MATRIX
    # =========================================================================

    def channel_receive_message(self, payload):
        """Create a mail.message in Odoo from an incoming Matrix event.

        Входящее из Matrix → создаём mail.message с тегом 'matrix'.
        Это дублирует переписку внутри Odoo.
        """
        body = payload.get('content', {}).get('body', '')
        sender = payload.get('sender', '')
        room_id = payload.get('room_id', '')

        print(
            f"[tier_matrix] channel_receive_message: "
            f"входящее из Matrix, sender={sender}, room={room_id}, body_len={len(body)}"
        )

        # Ищем пользователя по room_id чтобы привязать к нужному треду
        user_with_room = self.env['res.users'].sudo().search(
            [('tier_matrix_room_id', '=', room_id)], limit=1
        )

        vals = {
            'body': body,
            'message_type': 'email',
            'email_from': sender,
            'subject': f'Matrix: {sender}',
        }

        # Если нашли пользователя с этой комнатой — привязываем к его партнёру
        if user_with_room and user_with_room.partner_id:
            vals['author_id'] = False  # внешний отправитель

        msg = self.env['mail.message'].sudo().create(vals)

        # Помечаем тегом matrix
        matrix_tag = self.env['tier.channel.tag'].search([('code', '=', 'matrix')], limit=1)
        if matrix_tag:
            msg.channel_tag_ids = [(4, matrix_tag.id)]

        from odoo.addons.tier_communications.models.tier_router import TierRouter
        TierRouter(self.env).route_incoming(msg)

        print(
            f"[tier_matrix] channel_receive_message: "
            f"создано msg_id={msg.id} с тегом matrix"
        )
        return msg
