# -*- coding: utf-8 -*-
import logging

from odoo import _, api, fields, models
from odoo.tools import email_normalize

from .mail_sync_server import _extract_email_addresses

_logger = logging.getLogger(__name__)


class MailSyncMessageCrm(models.Model):
    _inherit = 'mail.sync.message'

    lead_ids = fields.Many2many(
        'crm.lead',
        'mail_sync_message_lead_rel',
        'message_id',
        'lead_id',
        string='Matched CRM Leads',
        help='CRM leads that received a log note for this message.',
    )
    is_routed_lead = fields.Boolean(
        string='Routed to CRM Lead',
        default=False,
        index=True,
        readonly=True,
    )
    lead_routed_date = fields.Datetime(string='CRM Routed On', readonly=True)

    def _primary_sender_email(self):
        """Return the main external sender email for lead matching."""
        self.ensure_one()
        for addr in _extract_email_addresses(self.email_from):
            normalized = email_normalize(addr)
            mailbox = email_normalize(self.server_id.user or '')
            if normalized and normalized != mailbox:
                return addr
        return False

    def _find_leads_for_emails(self, emails, partners):
        """Return CRM leads matching participant emails or linked partners."""
        Lead = self.env['crm.lead']
        leads = Lead.browse()
        seen = set()
        for addr in emails:
            normalized = email_normalize(addr)
            if not normalized:
                continue
            domain = [('active', '=', True)]
            if 'email_normalized' in Lead._fields:
                domain.extend([
                    '|',
                    ('email_normalized', '=', normalized),
                    ('email_from', 'ilike', addr),
                ])
            else:
                domain.append(('email_from', 'ilike', addr))
            for lead in Lead.search(domain):
                if lead.id not in seen:
                    seen.add(lead.id)
                    leads |= lead
        if partners:
            for lead in Lead.search([
                ('active', '=', True),
                ('partner_id', 'in', partners.ids),
            ]):
                if lead.id not in seen:
                    seen.add(lead.id)
                    leads |= lead
        return leads

    def _create_lead_for_message(self, sender_email, partner):
        """Create a CRM lead to capture unmatched catch-all mail."""
        self.ensure_one()
        Lead = self.env['crm.lead']
        name = (self.subject or '').strip() or sender_email or _('Inbox Mail')
        vals = {
            'name': name,
            'email_from': sender_email,
            'type': 'lead',
            'description': (self.body_text or '')[:2000],
        }
        if partner:
            vals['partner_id'] = partner.id
        if self.company_id:
            vals['company_id'] = self.company_id.id
        return Lead.create(vals)

    def _post_log_note_to_lead(self, lead):
        """Post one internal log note on a CRM lead; idempotent per lead."""
        self.ensure_one()
        if lead in self.lead_ids:
            return False
        attachment_ids = self._copy_attachments_for_post()
        posted = lead.message_post(
            body=self._build_log_note_body(),
            subject='[Inbox] %s' % (self.subject or ''),
            message_type='comment',
            subtype_xmlid='mail.mt_note',
            attachment_ids=attachment_ids,
        )
        mail_message = self.env['mail.message'].browse(posted) if isinstance(posted, int) else posted
        self.write({
            'lead_ids': [(4, lead.id)],
            'mail_message_ids': [(4, mail_message.id)],
        })
        return True

    def _route_to_leads(self):
        """Match participant emails to CRM leads and post log notes."""
        if 'crm.lead' not in self.env:
            return
        Lead = self.env['crm.lead']
        for message in self:
            server = message.server_id
            if not server.crm_route_enabled:
                continue
            emails = message._extract_participant_emails()
            partners = message._find_partners_for_emails(emails) if emails else self.env['res.partner'].browse()
            leads = message._find_leads_for_emails(emails, partners) if emails else Lead.browse()

            if not leads and server.crm_create_lead_if_unmatched:
                sender = message._primary_sender_email()
                if sender:
                    partner = message._find_partners_for_emails([sender])[:1]
                    leads = message._create_lead_for_message(sender, partner)

            if not leads:
                continue

            posted_any = False
            for lead in leads:
                try:
                    if message._post_log_note_to_lead(lead):
                        posted_any = True
                except Exception:
                    _logger.exception(
                        'Failed to post log note for sync message %s to lead %s',
                        message.id, lead.id,
                    )
            if posted_any:
                message.write({
                    'is_routed_lead': True,
                    'lead_routed_date': fields.Datetime.now(),
                })

    def _route_all(self):
        """Route synced mail to contacts and CRM leads."""
        super()._route_all()
        self._route_to_leads()
