# Copyright 2023 Moduon Team S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)

from odoo import api, fields, models


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

    def onchange(self, values, field_name, field_onchange):
        """Record which field was being changed."""
        if isinstance(field_name, list):
            names = set(field_name)
        elif field_name:
            names = {field_name}
        else:
            names = set()
        _self = self.with_context(changing_fields=names)
        return super(SaleOrderLine, _self).onchange(values, field_name, field_onchange)

    @api.depends("product_id", "product_uom_qty", "product_uom")
    def _compute_product_packaging_id(self):
        """Set a default packaging for sales if possible."""
        for line in self:
            if line.product_id != line.product_packaging_id.product_id:
                line.product_packaging_id = line._get_default_packaging(line.product_id)
        result = super()._compute_product_packaging_id()
        # If there's no way to package the desired qty, remove the packaging.
        # It is only done when the user is currently manually setting
        # `product_uom_qty` to zero. In other cases, we are maybe getting
        # default values and this difference will get fixed by other compute
        # methods later.
        if (
            self.env.context.get("changing_fields")
            and "product_uom_qty" not in self.env.context["changing_fields"]
        ):
            return result
        for line in self:
            if (
                line.product_uom_qty
                and line.product_packaging_id
                and line.product_uom
                and line.product_uom_qty
                != line.product_packaging_id._check_qty(
                    line.product_uom_qty, line.product_uom
                )
            ):
                line.product_packaging_id = False
        return result

    @api.model
    def _get_default_packaging(self, product):
        return fields.first(
            product.packaging_ids.filtered_domain([("sales", "=", True)])
        )

    @api.depends("product_packaging_id", "product_uom", "product_uom_qty")
    def _compute_product_packaging_qty(self):
        """Set a valid packaging quantity."""
        changing_fields = self.env.context.get("changing_fields", set())
        # Keep the packaging qty when changing the product
        if "product_id" in changing_fields and all(
            line.product_id and line.product_packaging_qty for line in self
        ):
            return
        result = super()._compute_product_packaging_qty()
        for line in self:
            if not line.product_packaging_id:
                continue
            # Reset to 1 packaging if it's empty or not a whole number
            if not line.product_packaging_qty or line.product_packaging_qty % 1:
                line.product_packaging_qty = int(
                    "product_uom_qty" not in changing_fields
                )
        return result

    @api.depends(
        "display_type",
        "product_id",
        "product_packaging_id",
        "product_packaging_qty",
    )
    def _compute_product_uom_qty(self):
        # Avoid a circular dependency. Upstream `product_uom_qty` has an
        # undeclared dependency over `product_packaging_qty`, which depends
        # again on `product_uom_qty`.
        _self = self.with_context(keep_product_packaging=True)
        result = super(SaleOrderLine, _self)._compute_product_uom_qty()
        return result
