# Copyright 2020 Le Filament
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

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


class AccountPaymentOrder(models.Model):
    _inherit = "account.payment.order"

    payment_line_amount = fields.Float(
        string="Total Opérations", compute="_compute_payment_line_amount"
    )
    bank_line_amount = fields.Float(
        string="Total Lignes de paiement", compute="_compute_bank_line_amount"
    )
    attachment_ids = fields.One2many(
        comodel_name="ir.attachment", compute="_compute_attachment_ids"
    )
    mandate_validity = fields.Boolean(
        "Mandats valides", compute="_compute_mandate_validity"
    )
    email_sent = fields.Boolean("Email envoyé aux coopératives", default=False)
    email_datetime = fields.Datetime("Date email envoyé aux coopératives")
    email_count = fields.Integer(string="Nombre de mails", compute="_compute_emails")

    # ------------------------------------------------------
    # Compute fields
    # ------------------------------------------------------
    def _compute_payment_line_amount(self):
        for po in self:
            po.payment_line_amount = sum(po.payment_line_ids.mapped("amount_currency"))

    def _compute_bank_line_amount(self):
        for po in self:
            po.bank_line_amount = sum(po.payment_ids.filtered(
                lambda p: not p.reversed_entry_id).mapped("amount_total_signed"))

    def _compute_attachment_ids(self):
        Attachment = self.env["ir.attachment"]
        for po in self:
            po.attachment_ids = Attachment.search(
                [
                    ("res_model", "=", "account.payment.order"),
                    ("res_id", "=", po.id),
                ]
            )

    def _compute_mandate_validity(self):
        for o in self:
            validity = o.mapped("payment_line_ids.mandate_id").filtered(
                lambda m: m.state != "valid"
            )
            if validity:
                o.mandate_validity = False
            else:
                o.mandate_validity = True

    # Emails
    def _compute_emails(self):
        for r in self:
            email_ids = self.env["mail.mail"].search(
                [("mail_message_id", "in", r.message_ids.ids)]
            )
            r.email_count = len(email_ids)

    # ------------------------------------------------------
    # Button function
    # ------------------------------------------------------
    def view_payment_line(self):
        tree_id = self.env.ref("cgscop_cotisation.scop_account_payment_line_tree").id
        search_id = self.env.ref(
            "cgscop_cotisation.scop_account_payment_line_search"
        ).id
        return {
            "type": "ir.actions.act_window",
            "name": "Lignes d'opérations",
            "res_model": "account.payment.line",
            "views": [[tree_id, "tree"]],
            "search_view_id": [search_id, "search"],
            "domain": [["order_id", "=", self.id]],
        }

    def view_account_move(self):
        tree_id = self.env.ref("cgscop_cotisation.scop_account_move_tree").id
        search_id = self.env.ref("cgscop_cotisation.scop_account_move_search").id
        return {
            "type": "ir.actions.act_window",
            "name": "Pièces comptables de l'ordre de prélèvement",
            "res_model": "account.move",
            "views": [[tree_id, "tree"], [False, "form"]],
            "search_view_id": [search_id, "search"],
            "domain": [["payment_order_id", "=", self.id]],
        }

    def view_wrong_iban(self):
        self.ensure_one()
        bank_ids = self.mapped("payment_line_ids.partner_bank_id").filtered(
            lambda b: b.acc_type != "iban"
        )
        return {
            "type": "ir.actions.act_window",
            "name": "Comptes bancaires",
            "res_model": "res.partner.bank",
            "views": [[False, "tree"], [False, "form"]],
            "domain": [["id", "in", bank_ids.ids]],
        }

    def view_wrong_mandate(self):
        self.ensure_one()
        mandate_ids = self.mapped("payment_line_ids.mandate_id").filtered(
            lambda m: m.state != "valid"
        )
        return {
            "type": "ir.actions.act_window",
            "name": "Mandats non valides",
            "res_model": "account.banking.mandate",
            "views": [[False, "tree"], [False, "form"]],
            "domain": [["id", "in", mandate_ids.ids]],
        }

    def action_send_email(self):
        self.ensure_one()
        try:
            template = self.env.ref("cgscop_cotisation.email_template_payment_order")
        except Exception:
            raise UserError(
                _(
                    "Aucun modèle d'e-mail n'a été trouvé pour envoyer un "
                    "e-mail à la DIRECCTE"
                )
            )
        # Get partners
        partner_ids = self.payment_line_ids.mapped("partner_id")
        for partner in partner_ids:
            template.with_context(partner_id=partner.id).send_mail(
                self.id,
            )
        self.email_sent = True
        self.email_datetime = fields.Datetime.now()

    def action_show_emails(self):
        return {
            "name": "Etat des mails envoyés",
            "type": "ir.actions.act_window",
            "view_mode": "tree",
            "views": [(False, "tree"), (False, "form")],
            "res_model": "mail.mail",
            "domain": [("mail_message_id", "in", self.message_ids.ids)],
        }

    # ------------------------------------------------------
    # Common function
    # ------------------------------------------------------
    def check_sepa_order(self):
        for order in self:
            if not order.sepa:
                msg = (
                    "Les comptes bancaires des coopératives "
                    "suivantes ne sont pas corrects : \n"
                )
                payment_line_ids = order.payment_line_ids.mapped("partner_bank_id")
                account_ids = payment_line_ids.filtered(lambda a: a.acc_type != "iban")
                for acc in account_ids:
                    msg += " - " + acc.partner_id.name + " - " + acc.acc_number + "\n"

                msg += (
                    "\nVeuillez corriger ces comptes bancaires pour "
                    "pouvoir valider l'ordre de prélèvement."
                )
                raise ValidationError(msg)
            else:
                return True

    # Email
    def get_email_values(self):
        self.ensure_one()
        partner_id = self.env["res.partner"].browse(self.env.context.get("partner_id"))
        partner_line_ids = self.payment_line_ids.filtered(
            lambda l: l.partner_id == partner_id
        )
        invoice_ids = partner_line_ids.mapped("move_line_id.move_id").filtered(
            "is_contribution"
        )
        return {
            "total": sum(partner_line_ids.mapped("amount_currency")),
            "date": partner_line_ids.mapped("date")[0],
            "bank": partner_line_ids.mapped("partner_bank_id.acc_number")[0],
            "deadline": invoice_ids.read_group(
                domain=[("id", "in", invoice_ids.ids)],
                fields=["year", "cotiz_quarter", "amount_total_signed"],
                groupby=["year", "cotiz_quarter"],
                orderby="year,cotiz_quarter",
                lazy=False,
            ),
        }

    def get_recipients(self):
        recipients = ",".join(map(lambda x: str(x), self._get_recipient().ids))
        return recipients

    def _get_recipient(self):
        partner_id = self.env["res.partner"].browse(self.env.context.get("partner_id"))
        if partner_id:
            tag_cotiz_id = self.env.company.tag_cotiz_id
            child_ids = partner_id.child_ids.filtered(
                lambda child: (tag_cotiz_id in child.category_id) and child.email
            )
            if partner_id.email:
                recipient_ids = partner_id + child_ids
            else:
                recipient_ids = child_ids

            return recipient_ids

    # ------------------------------------------------------
    # Override Parent
    # ------------------------------------------------------
    def open2generated(self):
        self.check_sepa_order()
        return super(AccountPaymentOrder, self).open2generated()

    def _prepare_move(self, bank_lines=None):
        res = super()._prepare_move(bank_lines=bank_lines)
        res["commercial_partner_id"] = bank_lines[0].partner_id.id
        res["partner_id"] = bank_lines[0].partner_id.id
        return res