# Copyright (C) 2025: 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 TestPurchaseOrder(TransactionCase):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()

        # Create a supplier
        cls.supplier = cls.env["res.partner"].create(
            {
                "name": "Test Supplier",
                "email": "supplier@test.com",
                "supplier_rank": 1,
            }
        )

        # Create a product template first, then get the variant
        cls.product_template = cls.env["product.template"].create(
            {
                "name": "Test Product PO",
                "type": "consu",
                "list_price": 150.0,
                "standard_price": 80.0,
            }
        )
        # Get the auto-created product variant
        cls.product = cls.product_template.product_variant_ids[0]

        # Create a purchase order
        cls.purchase_order = cls.env["purchase.order"].create(
            {
                "partner_id": cls.supplier.id,
            }
        )

        # Create purchase order line
        cls.po_line = cls.env["purchase.order.line"].create(
            {
                "order_id": cls.purchase_order.id,
                "product_id": cls.product.id,
                "product_qty": 10,
                "price_unit": 150.0,
                "discount1": 10.0,
                "discount2": 5.0,
                "discount3": 2.0,
            }
        )

    def test_po_line_discount_readonly(self):
        """Test that discount field is readonly in PO lines"""
        field = self.po_line._fields["discount"]
        self.assertTrue(field.readonly, "Discount field should be readonly in PO lines")

    def test_po_line_write_with_explicit_discounts(self):
        """Test writing PO line with explicit discounts"""
        self.po_line.write(
            {
                "discount": 25.0,  # Should be ignored
                "discount1": 12.0,
                "discount2": 8.0,
                "discount3": 4.0,
            }
        )

        self.assertEqual(self.po_line.discount1, 12.0)
        self.assertEqual(self.po_line.discount2, 8.0)
        self.assertEqual(self.po_line.discount3, 4.0)

    def test_po_line_legacy_discount(self):
        """Test legacy discount behavior in PO lines"""
        self.po_line.write(
            {
                "discount": 18.0,
            }
        )

        # Should map to discount1 and reset others
        self.assertEqual(self.po_line.discount1, 18.0)
        self.assertEqual(self.po_line.discount2, 0.0)
        self.assertEqual(self.po_line.discount3, 0.0)

    def test_po_line_price_calculation(self):
        """Test that price subtotal is calculated correctly with triple discount"""
        self.po_line.write(
            {
                "discount1": 15.0,
                "discount2": 10.0,
                "discount3": 5.0,
            }
        )

        # Base: 10 * 150 = 1500
        # After 15% discount: 1275
        # After 10% discount: 1147.5
        # After 5% discount: 1090.125
        expected_subtotal = 10 * 150 * 0.85 * 0.90 * 0.95
        self.assertAlmostEqual(self.po_line.price_subtotal, expected_subtotal, places=2)

    def test_multiple_po_lines(self):
        """Test multiple PO lines with different discounts"""
        line2 = self.env["purchase.order.line"].create(
            {
                "order_id": self.purchase_order.id,
                "product_id": self.product.id,
                "product_qty": 5,
                "price_unit": 120.0,
                "discount1": 20.0,
                "discount2": 15.0,
                "discount3": 10.0,
            }
        )

        # Verify both lines have correct discounts
        self.assertEqual(self.po_line.discount1, 15.0)
        self.assertEqual(line2.discount1, 20.0)
        self.assertEqual(line2.discount2, 15.0)
        self.assertEqual(line2.discount3, 10.0)

    def test_po_line_update_quantity(self):
        """Test updating quantity doesn't affect discounts"""
        initial_discount1 = self.po_line.discount1
        initial_discount2 = self.po_line.discount2

        self.po_line.write(
            {
                "product_qty": 20,
            }
        )

        # Discounts should remain unchanged
        self.assertEqual(self.po_line.discount1, initial_discount1)
        self.assertEqual(self.po_line.discount2, initial_discount2)
        # Quantity should be updated
        self.assertEqual(self.po_line.product_qty, 20)

    def test_po_line_update_price(self):
        """Test updating price doesn't affect discounts"""
        initial_discount1 = self.po_line.discount1

        self.po_line.write(
            {
                "price_unit": 200.0,
            }
        )

        # Discount should remain unchanged
        self.assertEqual(self.po_line.discount1, initial_discount1)
        # Price should be updated
        self.assertEqual(self.po_line.price_unit, 200.0)

    def test_po_with_zero_discounts(self):
        """Test PO line with all zero discounts"""
        self.po_line.write(
            {
                "discount1": 0.0,
                "discount2": 0.0,
                "discount3": 0.0,
            }
        )

        # All discounts should be zero
        self.assertEqual(self.po_line.discount, 0.0)
        self.assertEqual(self.po_line.discount1, 0.0)
        self.assertEqual(self.po_line.discount2, 0.0)
        self.assertEqual(self.po_line.discount3, 0.0)

        # Subtotal should be quantity * price
        expected = 10 * 150
        self.assertEqual(self.po_line.price_subtotal, expected)

    def test_po_line_combined_operations(self):
        """Test combined operations on PO line"""
        # Update multiple fields at once
        self.po_line.write(
            {
                "product_qty": 15,
                "price_unit": 175.0,
                "discount1": 18.0,
                "discount2": 12.0,
                "discount3": 6.0,
            }
        )

        # All fields should be updated correctly
        self.assertEqual(self.po_line.product_qty, 15)
        self.assertEqual(self.po_line.price_unit, 175.0)
        self.assertEqual(self.po_line.discount1, 18.0)
        self.assertEqual(self.po_line.discount2, 12.0)
        self.assertEqual(self.po_line.discount3, 6.0)

        # Calculate expected subtotal
        expected = 15 * 175 * 0.82 * 0.88 * 0.94
        self.assertAlmostEqual(self.po_line.price_subtotal, expected, places=2)

    def test_po_confirm_with_discounts(self):
        """Test confirming PO doesn't alter discounts"""
        self.po_line.write(
            {
                "discount1": 10.0,
                "discount2": 5.0,
                "discount3": 2.0,
            }
        )

        # Confirm the purchase order
        self.purchase_order.button_confirm()

        # Discounts should remain unchanged after confirmation
        self.assertEqual(self.po_line.discount1, 10.0)
        self.assertEqual(self.po_line.discount2, 5.0)
        self.assertEqual(self.po_line.discount3, 2.0)
