class TierRouter:
    """Plain Python router — not an Odoo model.

    Handles channel routing for outgoing messages and inbox fallback for incoming.
    Mailbox assignment is now manual-only (via wizard).
    """

    def __init__(self, env):
        self.env = env

    def route_outgoing(self, message, partner, source_model=None):
        """Assign channel tag to an outgoing message based on routing rules.

        Mailboxes are no longer auto-assigned — user does it manually.
        """
        channel = self._resolve_channel(partner)
        if channel:
            message.channel_tag_ids = [(4, channel.id)]

    def route_incoming(self, message):
        """Route an incoming message.

        If it's a reply — inherit mailboxes from parent.
        Otherwise — place in standard Odoo inbox.
        """
        parent = message.parent_id
        if parent and parent.mailbox_tag_ids:
            for tag in parent.mailbox_tag_ids:
                self.env['tier.mailbox.tag'].create({
                    'mailbox_id': tag.mailbox_id.id,
                    'message_id': message.id,
                })
        else:
            self._fallback_inbox(message)

    def _fallback_inbox(self, message):
        """Place message in the standard Odoo inbox via mail.notification."""
        partner = self.env.user.partner_id
        if not partner:
            return
        existing = self.env['mail.notification'].sudo().search([
            ('mail_message_id', '=', message.id),
            ('res_partner_id', '=', partner.id),
        ], limit=1)
        if not existing:
            self.env['mail.notification'].sudo().create({
                'mail_message_id': message.id,
                'res_partner_id': partner.id,
                'notification_type': 'inbox',
                'is_read': False,
            })

    def _resolve_channel(self, partner):
        """Return the best channel tag for partner from routing rules."""
        if not partner:
            return None

        rule = self.env['tier.routing.channel'].search(
            [('partner_id', '=', partner.id)],
            order='priority desc',
            limit=1,
        )
        if not rule:
            return None

        preferred = rule.preferred_channel_tag_id
        if preferred and preferred.active:
            return preferred

        for tag in rule.channel_tag_ids.filtered('active'):
            return tag

        return None
