# Part of Fusion Accounting. See LICENSE file for full copyright and licensing details.

from odoo import api, fields, models, _
from odoo.exceptions import UserError


class FusionFollowupSendWizard(models.TransientModel):
    """Wizard for previewing and manually sending payment follow-ups.

    Allows the user to review the email content, modify the message
    body, choose communication channels, and send the follow-up for
    one or more partners at once.
    """

    _name = 'fusion.followup.send.wizard'
    _description = "Fusion Follow-up Send Wizard"

    # ---- Context Fields ----
    followup_line_id = fields.Many2one(
        comodel_name='fusion.followup.line',
        string="Follow-up Record",
        readonly=True,
    )
    partner_id = fields.Many2one(
        comodel_name='res.partner',
        string="Partner",
        related='followup_line_id.partner_id',
        readonly=True,
    )
    followup_level_id = fields.Many2one(
        comodel_name='fusion.followup.level',
        string="Follow-up Level",
        related='followup_line_id.followup_level_id',
        readonly=True,
    )

    # ---- Editable Content ----
    email_subject = fields.Char(
        string="Subject",
        compute='_compute_email_preview',
        store=True,
        readonly=False,
    )
    email_body = fields.Html(
        string="Email Body",
        compute='_compute_email_preview',
        store=True,
        readonly=False,
        help="Edit the email body before sending. Changes apply only to this send.",
    )

    # ---- Channel Overrides ----
    do_send_email = fields.Boolean(
        string="Send Email",
        compute='_compute_channel_defaults',
        store=True,
        readonly=False,
    )
    do_send_sms = fields.Boolean(
        string="Send SMS",
        compute='_compute_channel_defaults',
        store=True,
        readonly=False,
    )
    do_print_letter = fields.Boolean(
        string="Print Letter",
        compute='_compute_channel_defaults',
        store=True,
        readonly=False,
    )
    do_join_invoices = fields.Boolean(
        string="Attach Invoices",
        compute='_compute_channel_defaults',
        store=True,
        readonly=False,
    )

    # ---- Informational ----
    overdue_amount = fields.Monetary(
        string="Overdue Amount",
        related='followup_line_id.overdue_amount',
        readonly=True,
        currency_field='currency_id',
    )
    overdue_count = fields.Integer(
        string="Overdue Invoices",
        related='followup_line_id.overdue_count',
        readonly=True,
    )
    currency_id = fields.Many2one(
        comodel_name='res.currency',
        related='followup_line_id.currency_id',
        readonly=True,
    )

    # --------------------------------------------------
    # Default Values
    # --------------------------------------------------

    @api.model
    def default_get(self, fields_list):
        """Populate the wizard from the active follow-up line."""
        defaults = super().default_get(fields_list)
        active_id = self.env.context.get('active_id')
        if active_id and self.env.context.get('active_model') == 'fusion.followup.line':
            defaults['followup_line_id'] = active_id
        return defaults

    # --------------------------------------------------
    # Computed Fields
    # --------------------------------------------------

    @api.depends('followup_level_id', 'partner_id')
    def _compute_email_preview(self):
        """Build a preview of the email subject and body.

        Uses the level's email template if set, otherwise falls back to
        the level description or a sensible default.
        """
        for wizard in self:
            level = wizard.followup_level_id
            partner = wizard.partner_id
            company = wizard.followup_line_id.company_id or self.env.company

            if level and level.email_template_id:
                template = level.email_template_id
                # Render the template for the partner
                rendered = template._render_field(
                    'body_html', [partner.id],
                    engine='inline_template',
                    compute_lang=True,
                )
                wizard.email_body = rendered.get(partner.id, '')
                rendered_subject = template._render_field(
                    'subject', [partner.id],
                    engine='inline_template',
                    compute_lang=True,
                )
                wizard.email_subject = rendered_subject.get(partner.id, '')
            else:
                wizard.email_subject = _(
                    "%(company)s - Payment Reminder",
                    company=company.name,
                )
                if level and level.description:
                    wizard.email_body = level.description
                else:
                    wizard.email_body = _(
                        "<p>Dear %(partner)s,</p>"
                        "<p>This is a reminder that your account has an outstanding "
                        "balance. Please arrange payment at your earliest convenience.</p>"
                        "<p>Best regards,<br/>%(company)s</p>",
                        partner=partner.name or _('Customer'),
                        company=company.name,
                    )

    @api.depends('followup_level_id')
    def _compute_channel_defaults(self):
        """Pre-fill channel toggles from the follow-up level configuration."""
        for wizard in self:
            level = wizard.followup_level_id
            if level:
                wizard.do_send_email = level.send_email
                wizard.do_send_sms = level.send_sms
                wizard.do_print_letter = level.send_letter
                wizard.do_join_invoices = level.join_invoices
            else:
                wizard.do_send_email = True
                wizard.do_send_sms = False
                wizard.do_print_letter = False
                wizard.do_join_invoices = False

    # --------------------------------------------------
    # Actions
    # --------------------------------------------------

    def action_send_followup(self):
        """Send the follow-up using the wizard-configured channels and content.

        Sends the (possibly edited) email, optionally triggers SMS,
        then advances the partner to the next follow-up level.

        :returns: ``True`` to close the wizard.
        :raises UserError: If no follow-up line is linked.
        """
        self.ensure_one()
        line = self.followup_line_id
        if not line:
            raise UserError(_("No follow-up record is linked to this wizard."))

        line._compute_overdue_values()
        if line.overdue_amount <= 0:
            line.followup_status = 'no_action_needed'
            raise UserError(_(
                "Partner '%s' no longer has any overdue balance. "
                "Follow-up cancelled.",
                line.partner_id.display_name,
            ))

        partner = line.partner_id

        # ---- Email ----
        if self.do_send_email:
            attachment_ids = []
            if self.do_join_invoices:
                attachment_ids = line._get_invoice_attachments(partner)

            mail_values = {
                'subject': self.email_subject,
                'body_html': self.email_body,
                'email_from': (
                    line.company_id.email
                    or self.env.user.email_formatted
                ),
                'email_to': partner.email,
                'author_id': self.env.user.partner_id.id,
                'res_id': partner.id,
                'model': 'res.partner',
                'attachment_ids': [(6, 0, attachment_ids)],
            }
            mail = self.env['mail.mail'].sudo().create(mail_values)
            mail.send()

        # ---- SMS ----
        if self.do_send_sms and line.followup_level_id.sms_template_id:
            try:
                line.followup_level_id.sms_template_id._send_sms(partner.id)
            except Exception:
                pass

        # ---- Advance Level ----
        level = line.followup_level_id
        if level:
            next_level = level._get_next_level()
            line.write({
                'date': fields.Date.context_today(self),
                'followup_level_id': next_level.id if next_level else level.id,
            })
        else:
            line.write({'date': fields.Date.context_today(self)})

        return {'type': 'ir.actions.act_window_close'}

    def action_preview_email(self):
        """Recompute the email preview after manual edits to the level.

        :returns: Action to reload the wizard form.
        """
        self.ensure_one()
        self._compute_email_preview()
        return {
            'type': 'ir.actions.act_window',
            'res_model': self._name,
            'res_id': self.id,
            'view_mode': 'form',
            'target': 'new',
        }
