# Copyright (C) 2020: Criptomart (https://criptomart.net)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo.tests import tagged
from odoo.tests.common import TransactionCase


@tagged("post_install", "-at_install")
class TestPricelist(TransactionCase):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()

        # Create tax
        cls.tax = cls.env["account.tax"].create(
            {
                "name": "Test Tax 10%",
                "amount": 10.0,
                "amount_type": "percent",
                "type_tax_use": "sale",
            }
        )

        # Create product
        cls.product = cls.env["product.product"].create(
            {
                "name": "Test Product Pricelist",
                "list_price": 100.0,
                "standard_price": 50.0,
                "taxes_id": [(6, 0, [cls.tax.id])],
                "last_purchase_price_received": 50.0,
                "last_purchase_price_compute_type": "without_discounts",
            }
        )

        # Create pricelist with last_purchase_price base
        cls.pricelist = cls.env["product.pricelist"].create(
            {
                "name": "Test Pricelist Last Purchase",
                "currency_id": cls.env.company.currency_id.id,
            }
        )

    def test_pricelist_item_base_last_purchase_price(self):
        """Test pricelist item with last_purchase_price base"""
        self.env["product.pricelist.item"].create(
            {
                "pricelist_id": self.pricelist.id,
                "compute_price": "formula",
                "base": "last_purchase_price",
                "price_discount": 0,
                "price_surcharge": 10.0,
                "applied_on": "3_global",
            }
        )

        # Compute price using pricelist
        price = self.pricelist._compute_price_rule(self.product, quantity=1, date=False)

        # Price should be based on last_purchase_price
        self.assertIn(self.product.id, price)
        # The exact price depends on the formula calculation

    def test_pricelist_item_with_discount(self):
        """Test pricelist item with discount on last_purchase_price"""
        self.env["product.pricelist.item"].create(
            {
                "pricelist_id": self.pricelist.id,
                "compute_price": "formula",
                "base": "last_purchase_price",
                "price_discount": 20.0,  # 20% discount
                "applied_on": "3_global",
            }
        )

        price = self.pricelist._compute_price_rule(self.product, quantity=1, date=False)

        # Expected: 50.0 - (50.0 * 0.20) = 40.0
        self.assertIn(self.product.id, price)
        self.assertEqual(price[self.product.id][0], 40.0)

    def test_pricelist_item_with_markup(self):
        """Test pricelist item with markup on last_purchase_price"""
        pricelist_item = self.env["product.pricelist.item"].create(
            {
                "pricelist_id": self.pricelist.id,
                "compute_price": "formula",
                "base": "last_purchase_price",
                "price_markup": 100.0,  # 100% markup (double the price)
                "applied_on": "3_global",
            }
        )

        # _compute_price should return the base price (last_purchase_price_received)
        result = pricelist_item._compute_price(
            self.product, quantity=1, uom=self.product.uom_id, date=False, currency=None
        )

        # Should return the last purchase price as base
        self.assertEqual(result, 50.0)

    def test_pricelist_item_compute_price_method(self):
        """Test _compute_price method of pricelist item"""
        pricelist_item = self.env["product.pricelist.item"].create(
            {
                "pricelist_id": self.pricelist.id,
                "compute_price": "formula",
                "base": "last_purchase_price",
                "price_markup": 50.0,
                "applied_on": "3_global",
            }
        )

        result = pricelist_item._compute_price(
            self.product, quantity=1, uom=self.product.uom_id, date=False, currency=None
        )

        # Should return last_purchase_price_received
        self.assertEqual(result, self.product.last_purchase_price_received)

    def test_pricelist_item_with_zero_last_purchase_price(self):
        """Test pricelist behavior when last_purchase_price is zero"""
        product_zero = self.env["product.product"].create(
            {
                "name": "Product Zero Price",
                "list_price": 100.0,
                "last_purchase_price_received": 0.0,
            }
        )

        self.env["product.pricelist.item"].create(
            {
                "pricelist_id": self.pricelist.id,
                "compute_price": "formula",
                "base": "last_purchase_price",
                "price_discount": 10.0,
                "applied_on": "3_global",
            }
        )

        price = self.pricelist._compute_price_rule(product_zero, quantity=1, date=False)

        # Should handle zero price gracefully
        self.assertIn(product_zero.id, price)
        self.assertEqual(price[product_zero.id][0], 0.0)

    def test_pricelist_multiple_products(self):
        """Test pricelist calculation with multiple products"""
        product2 = self.env["product.product"].create(
            {
                "name": "Test Product 2",
                "list_price": 200.0,
                "last_purchase_price_received": 100.0,
            }
        )

        self.env["product.pricelist.item"].create(
            {
                "pricelist_id": self.pricelist.id,
                "compute_price": "formula",
                "base": "last_purchase_price",
                "price_discount": 10.0,
                "applied_on": "3_global",
            }
        )

        products = self.product | product2

        # Test with both products
        for product in products:
            price = self.pricelist._compute_price_rule(product, quantity=1, date=False)
            self.assertIn(product.id, price)

    def test_pricelist_item_selection_add(self):
        """Test that last_purchase_price is added to base selection"""
        pricelist_item_model = self.env["product.pricelist.item"]
        base_field = pricelist_item_model._fields["base"]

        # Check that last_purchase_price is in the selection
        selection_values = [item[0] for item in base_field.selection]
        self.assertIn("last_purchase_price", selection_values)

    def test_product_price_compute_fallback(self):
        """Test price_compute method fallback for last_purchase_price"""
        result = self.product.price_compute("last_purchase_price")

        # Should return dummy value 1.0 for all products
        self.assertEqual(result[self.product.id], 1.0)

    def test_pricelist_with_different_currencies(self):
        """Test pricelist with different currency (if applicable)"""
        # This test is optional and depends on multi-currency setup
        eur = self.env.ref("base.EUR", raise_if_not_found=False)
        if not eur:
            self.skipTest("EUR currency not available")

        pricelist_eur = self.env["product.pricelist"].create(
            {
                "name": "Test Pricelist EUR",
                "currency_id": eur.id,
            }
        )

        self.env["product.pricelist.item"].create(
            {
                "pricelist_id": pricelist_eur.id,
                "compute_price": "formula",
                "base": "last_purchase_price",
                "price_discount": 0,
                "applied_on": "3_global",
            }
        )

        # Price calculation should work with different currency
        price = pricelist_eur._compute_price_rule(self.product, quantity=1, date=False)

        self.assertIn(self.product.id, price)
