import re
from markupsafe import Markup

from odoo import api, models

CARD_IMAGE_URL = re.compile(r'src=".*?/web/image/card.campaign/[0-9]+/image_preview"')
CARD_PREVIEW_URL = re.compile(r'href=".*?/cards/[0-9]+/preview"')


class MailComposeMessage(models.TransientModel):
    _inherit = 'mail.compose.message'

    def _prepare_mail_values_dynamic(self, res_ids):
        """Replace generic card urls with the specific res_id url."""
        mail_values_all = super()._prepare_mail_values_dynamic(res_ids)

        if campaign := self.mass_mailing_id.card_campaign_id:
            card_from_res_id = self.env['card.card'].search_fetch(
                [('campaign_id', '=', campaign.id), ('res_id', 'in', res_ids)],
                ['res_id'],
            ).grouped('res_id')

            processed_bodies = self._process_generic_card_url_body([
                (card_from_res_id[res_id], mail_values.get('body_html'))
                for res_id, mail_values in mail_values_all.items()
            ])
            for mail_values, body in zip(mail_values_all.values(), processed_bodies):
                if body is not None:
                    mail_values['body_html'] = body

        return mail_values_all

    @api.model
    def _process_generic_card_url_body(self, card_body_pairs: list[tuple[models.Model, str]]) -> list[str]:
        """Update the bodies with the specific card url for that res_id and create a card.

        example: (1, "/cards/9/preview") -> (1, "/cards/9/1/abchashtoken/preview") + new card as side-effect

        :return: processed bodies in the order they were received
        """
        bodies = []
        for card, body in card_body_pairs:
            if body:
                def fill_card_image_url(match):
                    return Markup('src="{}"').format(card._get_path('card.jpg'))

                def fill_card_preview_url(match):
                    return Markup('href="{}"').format(card._get_path('preview'))

                body_is_markup = False
                if isinstance(body, Markup):
                    body_is_markup = True
                body = re.sub(CARD_IMAGE_URL, fill_card_image_url, body)
                body = re.sub(CARD_PREVIEW_URL, fill_card_preview_url, body)
                if body_is_markup:
                    body = Markup(body)
            bodies.append(body)
        return bodies
