# Copyright 2017 Tecnativa - David Vidal
# Copyright 2023 Simone Rubino - Aion Tech
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo.tests import Form

from odoo.addons.base.tests.common import BaseCommon


class TestInvoiceTripleDiscount(BaseCommon):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.Account = cls.env["account.account"]
        cls.AccountMove = cls.env["account.move"]
        cls.AccountMoveLine = cls.env["account.move.line"]
        cls.AccountTax = cls.env["account.tax"]
        cls.Partner = cls.env["res.partner"]
        cls.Journal = cls.env["account.journal"]

        cls.tax = cls.AccountTax.create(
            {
                "name": "TAX 15%",
                "amount_type": "percent",
                "type_tax_use": "purchase",
                "amount": 15.0,
                "country_id": cls.env.ref("base.us").id,
            }
        )
        cls.account = cls.Account.create(
            {
                "name": "Test account",
                "code": "TEST",
                "account_type": "asset_receivable",
                "reconcile": True,
            }
        )
        cls.sale_journal = cls.Journal.search([("type", "=", "sale")], limit=1)

    def create_simple_invoice(self, amount):
        invoice_form = Form(
            self.AccountMove.with_context(
                default_move_type="out_invoice",
                default_journal_id=self.sale_journal.id,
            )
        )
        invoice_form.partner_id = self.partner

        with invoice_form.invoice_line_ids.new() as line_form:
            line_form.name = "Line 1"
            line_form.quantity = 1
            line_form.price_unit = amount
            line_form.tax_ids.clear()
            line_form.tax_ids.add(self.tax)

        invoice = invoice_form.save()
        return invoice

    def test_01_discounts(self):
        """Tests multiple discounts in line with taxes"""
        invoice = self.create_simple_invoice(200)

        invoice_form = Form(invoice)
        with invoice_form.invoice_line_ids.edit(0) as line_form:
            line_form.discount1 = 50.0
        invoice_form.save()

        invoice_line = invoice.invoice_line_ids[0]

        # Adds a first discount
        self.assertEqual(invoice.amount_total, 115.0)

        # Adds a second discount over the price calculated before
        with invoice_form.invoice_line_ids.edit(0) as line_form:
            line_form.discount2 = 40.0
        invoice_form.save()
        self.assertEqual(invoice.amount_total, 69.0)

        # Adds a third discount over the price calculated before
        with invoice_form.invoice_line_ids.edit(0) as line_form:
            line_form.discount3 = 50.0
        invoice_form.save()
        self.assertEqual(invoice.amount_total, 34.5)

        # Deletes first discount
        with invoice_form.invoice_line_ids.edit(0) as line_form:
            line_form.discount1 = 0
        invoice_form.save()
        self.assertEqual(invoice.amount_total, 69)

        # Charge 5% over price:
        with invoice_form.invoice_line_ids.edit(0) as line_form:
            line_form.discount1 = -5
        invoice_form.save()
        self.assertEqual(invoice.amount_total, 72.45)

        self.assertEqual(invoice_line.price_unit, 200)

    def test_02_discounts_multiple_lines(self):
        invoice = self.create_simple_invoice(200)
        invoice_form = Form(invoice)
        with invoice_form.invoice_line_ids.new() as line_form:
            line_form.name = "Line 2"
            line_form.quantity = 1
            line_form.price_unit = 500
            line_form.tax_ids.clear()
        invoice_form.save()

        invoice_line2 = invoice.invoice_line_ids[1]
        self.assertEqual(invoice_line2.price_subtotal, 500.0)

        with invoice_form.invoice_line_ids.edit(1) as line_form:
            line_form.discount3 = 50.0
        invoice_form.save()
        self.assertEqual(invoice.amount_total, 480.0)

        with invoice_form.invoice_line_ids.edit(0) as line_form:
            line_form.discount1 = 50.0
        invoice_form.save()
        self.assertEqual(invoice.amount_total, 365.0)

    def test_03_discounts_decimals_price(self):
        """
        Tests discount with decimals price
        causing a round up after discount
        """
        invoice = self.create_simple_invoice(0)
        invoice_form = Form(invoice)
        with invoice_form.invoice_line_ids.edit(0) as line_form:
            line_form.name = "Line Decimals"
            line_form.quantity = 9950
            line_form.price_unit = 0.14
            line_form.tax_ids.clear()
        invoice_form.save()

        invoice_line1 = invoice.invoice_line_ids[0]

        self.assertEqual(invoice_line1.price_subtotal, 1393.0)

        with invoice_form.invoice_line_ids.edit(0) as line_form:
            line_form.discount1 = 15.0
        invoice_form.save()

        self.assertEqual(invoice_line1.price_subtotal, 1184.05)

    def test_04_discounts_decimals_tax(self):
        """
        Tests amount tax with discount
        """
        invoice = self.create_simple_invoice(0)
        invoice_form = Form(invoice)
        with invoice_form.invoice_line_ids.edit(0) as line_form:
            line_form.name = "Line Decimals"
            line_form.quantity = 9950
            line_form.price_unit = 0.14
            line_form.discount1 = 0
            line_form.discount2 = 0
        invoice_form.save()

        self.assertEqual(invoice.amount_tax, 208.95)
        with invoice_form.invoice_line_ids.edit(0) as line_form:
            line_form.discount1 = 15.0
        invoice_form.save()

    def test_06_round_discount(self):
        """Discount value is rounded correctly"""
        invoice = self.create_simple_invoice(0)
        invoice_line = invoice.invoice_line_ids[0]
        invoice_line.discount1 = 100
        self.assertEqual(invoice_line.discount1, 100)
        self.assertEqual(invoice_line.discount, 100)

    def test_07_round_tax_discount(self):
        """Discount value is rounded correctly when taxes change"""
        invoice = self.create_simple_invoice(0)
        invoice_line = invoice.invoice_line_ids[0]
        invoice_line.discount1 = 100
        invoice_line.tax_ids = False
        self.assertEqual(invoice_line.discount1, 100)
        self.assertEqual(invoice_line.discount, 100)

    def test_09_create_with_main_discount(self):
        """
        Tests if creating a invoice line with main discount field
        set correctly discount1, discount2 and discount3
        """
        invoice = self.create_simple_invoice(0)

        invoice_line2 = self.AccountMoveLine.create(
            {
                "move_id": invoice.id,
                "name": "Line With Main Discount",
                "quantity": 1,
                "price_unit": 1000,
                "discount": 10,
                "tax_ids": [],
            }
        )

        # 1000 * 0.9
        self.assertEqual(invoice_line2.price_subtotal, 900.0)
        self.assertEqual(invoice_line2.discount1, 10.0)
        self.assertEqual(invoice_line2.discount2, 0.0)
        self.assertEqual(invoice_line2.discount3, 0.0)

    def test_10_create_invoice_with_discounts(self):
        invoice = self.env["account.move"].create(
            {
                "partner_id": self.partner.id,
                "move_type": "out_invoice",
                "invoice_line_ids": [
                    (
                        0,
                        0,
                        {
                            "name": "Line 1",
                            "quantity": 1,
                            "price_unit": 100,
                            "discount1": 30,
                            "discount2": 20,
                            "discount3": 10,
                        },
                    )
                ],
            }
        )
        invoice_line1 = invoice.invoice_line_ids[0]
        self.assertEqual(invoice_line1.discount1, 30.0)
        self.assertEqual(invoice_line1.discount2, 20.0)
        self.assertEqual(invoice_line1.discount3, 10.0)

    def test_tax_compute_with_lock_date(self):
        # Check that the tax computation works even if the lock date is set
        invoice = self.create_simple_invoice(0)
        invoice_form = Form(invoice)
        with invoice_form.invoice_line_ids.edit(0) as line_form:
            line_form.name = "Line Decimals"
            line_form.quantity = 9950
            line_form.price_unit = 0.14
            line_form.discount1 = 10
            line_form.discount2 = 20
        invoice_form.save()
        invoice.action_post()
        self.env.user.company_id.fiscalyear_lock_date = "2000-01-01"
