# Copyright 2025 Your Name or Company
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import _, models, api, fields
import logging

_logger = logging.getLogger(__name__)


class StockInventory(models.Model):
    _inherit = "stock.inventory"

    include_exhausted_products = fields.Boolean(
        string="Include Exhausted Products",
        help="If enabled, products with zero stock will be included "
        "in the inventory adjustment by creating zero-quantity quants.",
        default=False,
    )

    def _create_zero_quants(self, locations, products):
        """Create zero-quantity quants for products without existing quants.

        This method creates stock quants with zero quantity for storable products
        that don't have existing quants in the specified locations. This allows
        these products to be included in inventory adjustments even when they
        have no current stock.

        Args:
            locations (stock.location recordset): Locations to check
            products (product.product recordset): Products to process
        """
        Quant = self.env["stock.quant"]

        # Get existing quants to avoid duplicates
        existing_quants = Quant.search(
            [
                ("product_id", "in", products.ids),
                ("location_id", "in", locations.ids),
            ]
        )
        existing_combinations = {
            (q.product_id.id, q.location_id.id) for q in existing_quants
        }

        quants_to_create = []
        for location in locations:
            for product in products.filtered(
                lambda p: p.type == "product" and p.active
            ):
                if (product.id, location.id) not in existing_combinations:
                    _logger.debug(
                        "Creating zero quant for product %s in location %s",
                        product.name,
                        location.name,
                    )
                    quants_to_create.append(
                        {
                            "product_id": product.id,
                            "location_id": location.id,
                            "quantity": 0,
                            "company_id": location.company_id.id or self.env.company.id,
                        }
                    )

        if quants_to_create:
            Quant.create(quants_to_create)

    def _get_quants(self, locations):
        """Override to include zero-quantity quants when requested.

        This method extends the base functionality to optionally include
        products with zero stock by creating zero-quantity quants before
        retrieving the final quant list.

        Args:
            locations (stock.location recordset): Locations for inventory

        Returns:
            stock.quant recordset: Quants to include in inventory
        """
        quants = super()._get_quants(locations)

        if self.include_exhausted_products:
            # Determine products based on selection criteria
            if self.product_selection == "category":
                products = self.env["product.product"].search(
                    [("categ_id", "child_of", self.category_id.id)]
                )
            elif self.product_selection in ("manual", "one", "lot"):
                products = self.product_ids
            else:  # "all"
                products = self.env["product.product"].search(
                    [("type", "=", "product")]
                )

            self._create_zero_quants(locations, products)
            # Re-fetch quants to include newly created ones
            return super()._get_quants(locations)

        return quants


class StockQuant(models.Model):
    _inherit = "stock.quant"

    @api.model
    def _unlink_zero_quants(self):
        """Override to only unlink zero quants for archived products.

        This method modifies the default behavior to preserve zero quants
        for active products while still removing them for archived products.
        This is useful when using the 'Include Exhausted Products' feature.
        """
        precision_digits = max(
            6, self.sudo().env.ref("product.decimal_product_uom").digits * 2
        )
        # Use a select instead of ORM search for UoM robustness.
        # Join with product_product and product_template to check if product is active
        query = """SELECT sq.id FROM stock_quant sq
                   INNER JOIN product_product pp ON sq.product_id = pp.id
                   INNER JOIN product_template pt ON pp.product_tmpl_id = pt.id
                   WHERE (round(sq.quantity::numeric, %s) = 0 OR sq.quantity IS NULL)
                   AND round(sq.reserved_quantity::numeric, %s) = 0
                   AND (round(sq.inventory_quantity::numeric, %s) = 0 OR sq.inventory_quantity IS NULL)
                   AND sq.user_id IS NULL
                   AND (pp.active = false OR pt.active = false);"""
        params = (precision_digits, precision_digits, precision_digits)
        self.env.cr.execute(query, params)
        quant_ids = self.env["stock.quant"].browse(
            [quant["id"] for quant in self.env.cr.dictfetchall()]
        )
        quant_ids.sudo().unlink()
