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

import base64

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


class AccountMove(models.Model):
    _inherit = 'account.move'

    poynt_refunded = fields.Boolean(
        string="Refunded via Poynt",
        readonly=True,
        copy=False,
        default=False,
    )
    poynt_refund_count = fields.Integer(
        string="Poynt Refund Count",
        compute='_compute_poynt_refund_count',
    )
    has_poynt_receipt = fields.Boolean(
        string="Has Poynt Receipt",
        compute='_compute_has_poynt_receipt',
    )

    @api.depends('reversal_move_ids')
    def _compute_poynt_refund_count(self):
        for move in self:
            if move.move_type == 'out_invoice':
                move.poynt_refund_count = len(move.reversal_move_ids.filtered(
                    lambda r: r.poynt_refunded
                ))
            else:
                move.poynt_refund_count = 0

    def _compute_has_poynt_receipt(self):
        for move in self:
            move.has_poynt_receipt = bool(move._get_poynt_transaction_for_receipt())

    def action_view_poynt_refunds(self):
        """Open the credit notes linked to this invoice that were refunded via Poynt."""
        self.ensure_one()
        refund_moves = self.reversal_move_ids.filtered(lambda r: r.poynt_refunded)
        action = {
            'name': _("Poynt Refunds"),
            'type': 'ir.actions.act_window',
            'res_model': 'account.move',
            'view_mode': 'list,form',
            'domain': [('id', 'in', refund_moves.ids)],
            'context': {'default_move_type': 'out_refund'},
        }
        if len(refund_moves) == 1:
            action['view_mode'] = 'form'
            action['res_id'] = refund_moves.id
        return action

    def _get_poynt_transaction_for_receipt(self):
        """Find the Poynt transaction linked to this invoice or credit note."""
        self.ensure_one()
        domain = [
            ('provider_id.code', '=', 'poynt'),
            ('poynt_transaction_id', '!=', False),
            ('state', '=', 'done'),
        ]
        if self.move_type == 'out_invoice':
            domain.append(('invoice_ids', 'in', self.ids))
        elif self.move_type == 'out_refund':
            domain += [
                ('operation', '=', 'refund'),
                ('invoice_ids', 'in', self.ids),
            ]
        else:
            return self.env['payment.transaction']

        return self.env['payment.transaction'].sudo().search(
            domain, order='id desc', limit=1,
        )

    def action_resend_poynt_receipt(self):
        """Resend the Poynt payment/refund receipt email to the customer."""
        self.ensure_one()
        tx = self._get_poynt_transaction_for_receipt()
        if not tx:
            raise UserError(_(
                "No completed Poynt transaction found for this document."
            ))

        template = self.env.ref(
            'fusion_poynt.mail_template_poynt_receipt',
            raise_if_not_found=False,
        )
        if not template:
            raise UserError(_("Receipt email template not found."))

        report = self.env.ref(
            'fusion_poynt.action_report_poynt_receipt',
            raise_if_not_found=False,
        )
        attachment_ids = []
        if report:
            pdf_content, _content_type = report.sudo()._render_qweb_pdf(
                report_ref='fusion_poynt.action_report_poynt_receipt',
                res_ids=tx.ids,
            )
            prefix = "Refund_Receipt" if self.move_type == 'out_refund' else "Payment_Receipt"
            filename = f"{prefix}_{tx.reference}.pdf"
            att = self.env['ir.attachment'].create({
                'name': filename,
                'type': 'binary',
                'datas': base64.b64encode(pdf_content),
                'res_model': self._name,
                'res_id': self.id,
                'mimetype': 'application/pdf',
            })
            attachment_ids = [att.id]

        template.send_mail(tx.id, force_send=True)

        is_refund = self.move_type == 'out_refund'
        label = _("Refund") if is_refund else _("Payment")
        self.message_post(
            body=_(
                "%(label)s receipt resent to %(email)s.",
                label=label,
                email=tx.partner_id.email,
            ),
            message_type='notification',
            subtype_xmlid='mail.mt_note',
            attachment_ids=attachment_ids,
        )

        return {
            'type': 'ir.actions.client',
            'tag': 'display_notification',
            'params': {
                'title': _("Receipt Sent"),
                'message': _("The receipt has been sent to %s.",
                             tx.partner_id.email),
                'type': 'success',
                'sticky': False,
            },
        }

    def action_open_poynt_payment_wizard(self):
        """Open the Poynt payment collection wizard for this invoice."""
        self.ensure_one()
        return {
            'name': _("Collect Poynt Payment"),
            'type': 'ir.actions.act_window',
            'res_model': 'poynt.payment.wizard',
            'view_mode': 'form',
            'target': 'new',
            'context': {
                'active_model': 'account.move',
                'active_id': self.id,
            },
        }

    def action_open_poynt_refund_wizard(self):
        """Open the Poynt refund wizard for this credit note."""
        self.ensure_one()
        return {
            'name': _("Refund via Poynt"),
            'type': 'ir.actions.act_window',
            'res_model': 'poynt.refund.wizard',
            'view_mode': 'form',
            'target': 'new',
            'context': {
                'active_model': 'account.move',
                'active_id': self.id,
            },
        }

    def _get_original_poynt_transaction(self):
        """Find the Poynt payment transaction from the reversed invoice.

        For credit notes created via the "Reverse" action, the
        ``reversed_entry_id`` links back to the original invoice.
        We look for a confirmed Poynt transaction on that invoice.
        """
        self.ensure_one()
        origin_invoice = self.reversed_entry_id
        if not origin_invoice:
            return self.env['payment.transaction']

        tx = self.env['payment.transaction'].sudo().search([
            ('invoice_ids', 'in', origin_invoice.ids),
            ('state', '=', 'done'),
            ('provider_id.code', '=', 'poynt'),
            ('poynt_transaction_id', '!=', False),
            ('poynt_voided', '=', False),
        ], order='id desc', limit=1)

        if not tx:
            tx = self.env['payment.transaction'].sudo().search([
                ('invoice_ids', 'in', origin_invoice.ids),
                ('state', 'in', ('done', 'cancel')),
                ('provider_id.code', '=', 'poynt'),
                ('poynt_transaction_id', '!=', False),
            ], order='id desc', limit=1)

        return tx
