from odoo.tests.common import TransactionCase


class TestStockInventoryExhausted(TransactionCase):
    def setUp(self):
        super().setUp()
        # Create test products
        self.product_with_stock = self.env["product.product"].create(
            {
                "name": "Product With Stock",
                "type": "product",
                "categ_id": self.env.ref("product.product_category_all").id,
            }
        )

        self.product_without_stock = self.env["product.product"].create(
            {
                "name": "Product Without Stock",
                "type": "product",
                "categ_id": self.env.ref("product.product_category_all").id,
            }
        )

        # Create test location
        self.location = self.env["stock.location"].create(
            {
                "name": "Test Location",
                "usage": "internal",
            }
        )

        # Create initial stock for one product
        self.env["stock.quant"].create(
            {
                "product_id": self.product_with_stock.id,
                "location_id": self.location.id,
                "quantity": 10.0,
            }
        )

    def test_inventory_without_exhausted_products_flag(self):
        """Test that without the flag, zero stock products are not included"""
        inventory = self.env["stock.inventory"].create(
            {
                "name": "Test Inventory without flag",
                "location_ids": [(6, 0, [self.location.id])],
                "product_selection": "all",
                "include_exhausted_products": False,
            }
        )

        inventory.action_start()

        # Should only have quants for products with existing stock
        self.assertTrue(
            any(
                q.product_id == self.product_with_stock
                for q in inventory.stock_quant_ids
            )
        )
        self.assertFalse(
            any(
                q.product_id == self.product_without_stock
                for q in inventory.stock_quant_ids
            )
        )

    def test_inventory_with_exhausted_products_flag(self):
        """Test that with the flag, zero stock products are included"""
        inventory = self.env["stock.inventory"].create(
            {
                "name": "Test Inventory with flag",
                "location_ids": [(6, 0, [self.location.id])],
                "product_selection": "all",
                "include_exhausted_products": True,
            }
        )

        inventory.action_start()

        # Should have quants for both products (including zero stock product)
        self.assertTrue(
            any(
                q.product_id == self.product_with_stock
                for q in inventory.stock_quant_ids
            )
        )
        self.assertTrue(
            any(
                q.product_id == self.product_without_stock
                for q in inventory.stock_quant_ids
            )
        )

        # Check that zero stock product has quantity 0
        zero_quant = inventory.stock_quant_ids.filtered(
            lambda q: q.product_id == self.product_without_stock
        )
        self.assertEqual(zero_quant.quantity, 0.0)

    def test_inventory_manual_selection_with_exhausted_flag(self):
        """Test manual product selection with exhausted products flag"""
        inventory = self.env["stock.inventory"].create(
            {
                "name": "Test Manual Selection",
                "location_ids": [(6, 0, [self.location.id])],
                "product_selection": "manual",
                "product_ids": [(6, 0, [self.product_without_stock.id])],
                "include_exhausted_products": True,
            }
        )

        inventory.action_start()

        # Should have quant for the selected product even if it has zero stock
        self.assertTrue(
            any(
                q.product_id == self.product_without_stock
                for q in inventory.stock_quant_ids
            )
        )
        zero_quant = inventory.stock_quant_ids.filtered(
            lambda q: q.product_id == self.product_without_stock
        )
        self.assertEqual(zero_quant.quantity, 0.0)

    def test_inventory_category_selection_with_exhausted_flag(self):
        """Test category selection with exhausted products flag"""
        # Create a specific category
        test_category = self.env["product.category"].create({"name": "Test Category"})

        # Create product in this category
        product_in_category = self.env["product.product"].create(
            {
                "name": "Product In Category",
                "type": "product",
                "categ_id": test_category.id,
            }
        )

        inventory = self.env["stock.inventory"].create(
            {
                "name": "Test Category Selection",
                "location_ids": [(6, 0, [self.location.id])],
                "product_selection": "category",
                "category_id": test_category.id,
                "include_exhausted_products": True,
            }
        )

        inventory.action_start()

        # Should have quant for the product in category even if it has zero stock
        self.assertTrue(
            any(q.product_id == product_in_category for q in inventory.stock_quant_ids)
        )

    def test_create_zero_quants_only_for_product_type(self):
        """Test that zero quants are only created for products with type 'product'"""
        # Create a service product
        service_product = self.env["product.product"].create(
            {
                "name": "Service Product",
                "type": "service",
            }
        )

        inventory = self.env["stock.inventory"].create(
            {
                "name": "Test Service Product",
                "location_ids": [(6, 0, [self.location.id])],
                "product_selection": "manual",
                "product_ids": [(6, 0, [service_product.id])],
                "include_exhausted_products": True,
            }
        )

        inventory.action_start()

        # Should not create quants for service products
        self.assertFalse(
            any(q.product_id == service_product for q in inventory.stock_quant_ids)
        )

    def test_no_duplicate_quants_created(self):
        """Test that no duplicate quants are created if they already exist"""
        # Create a quant with zero quantity manually
        existing_quant = self.env["stock.quant"].create(
            {
                "product_id": self.product_without_stock.id,
                "location_id": self.location.id,
                "quantity": 0.0,
            }
        )

        inventory = self.env["stock.inventory"].create(
            {
                "name": "Test No Duplicates",
                "location_ids": [(6, 0, [self.location.id])],
                "product_selection": "manual",
                "product_ids": [(6, 0, [self.product_without_stock.id])],
                "include_exhausted_products": True,
            }
        )

        inventory.action_start()

        # Should use existing quant, not create a new one
        quants_for_product = self.env["stock.quant"].search(
            [
                ("product_id", "=", self.product_without_stock.id),
                ("location_id", "=", self.location.id),
            ]
        )
        self.assertEqual(len(quants_for_product), 1)
        self.assertEqual(quants_for_product.id, existing_quant.id)

    def test_field_default_value(self):
        """Test that include_exhausted_products field defaults to False"""
        inventory = self.env["stock.inventory"].create(
            {
                "name": "Test Default Value",
                "location_ids": [(6, 0, [self.location.id])],
            }
        )

        self.assertFalse(inventory.include_exhausted_products)
