# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, fields, models


class SaleOrder(models.Model):
    _inherit = "sale.order"

    one_invoice_per_shipping = fields.Boolean(
        compute="_compute_one_invoice_per_shipping",
        store=True,
        index=True,
    )

    @api.depends("partner_invoice_id")
    def _compute_one_invoice_per_shipping(self):
        """
        Compute this field (instead a related) to avoid computing all
        related sale orders if option changed on partner level.
        """
        for order in self:
            order.one_invoice_per_shipping = (
                order.partner_invoice_id.one_invoice_per_shipping
            )

    def generate_invoices(
        self,
        companies=None,
        invoicing_mode="standard",
        last_execution_field="invoicing_mode_standard_last_execution",
    ):
        saleorders = super().generate_invoices(
            companies=companies,
            invoicing_mode=invoicing_mode,
            last_execution_field=last_execution_field,
        )
        # Validate the preceding generated invoices in draft mode.
        description = self.env._(
            "Validate the invoices generated by shipping for the "
            "invoicing mode %(invoicing_mode_name)s"
        )
        self.with_delay(
            description=description
        )._validate_per_shipping_generated_invoices(
            companies=companies, invoicing_mode=invoicing_mode
        )

        return saleorders

    @api.model
    def _validate_per_shipping_generated_invoices(
        self, companies=None, invoicing_mode="standard"
    ) -> str:
        """
            This will validate all draft invoices that have been generated.

        :param companies: _description_, defaults to None
        :type companies: _type_, optional
        :param invoicing_mode: _description_, defaults to "standard"
        :type invoicing_mode: str, optional
        :return: String result for queue job
        :rtype: AccountMove
        """
        if companies is None:
            companies = self.env.company
        invoices = self.env["account.move"].search(
            self._get_per_shipping_to_validate_invoices_domain(
                companies=companies, invoicing_mode=invoicing_mode
            )
        )
        for invoice in invoices:
            invoice.with_delay()._validate_invoice()
        for partner, __invoices in invoices.partition("partner_id").items():
            partner._update_next_invoice_date()
        return ",".join(invoices.mapped("display_name"))

    def _get_per_shipping_to_validate_invoices_domain(
        self, companies, invoicing_mode="standard"
    ) -> list:
        """
            This will return the domain for invoices that should be posted.

        :return: Domain
        :rtype: list
        """
        return [
            ("company_id", "in", companies.ids),
            ("move_type", "in", ("out_invoice", "out_refund")),
            ("state", "=", "draft"),
            ("partner_id.one_invoice_per_shipping", "=", True),
            ("partner_id.invoicing_mode", "=", invoicing_mode),
        ]
