# This file is part of Tryton.  The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from decimal import Decimal

from trytond.model import fields
from trytond.modules.currency.fields import Monetary
from trytond.modules.product import price_digits, round_price
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval


class Line(metaclass=PoolMeta):
    __name__ = 'sale.line'

    base_price = Monetary(
        "Base Price", currency='currency', digits=price_digits,
        states={
            'invisible': Eval('type') != 'line',
            'readonly': Eval('sale_state') != 'draft',
            })

    discount_rate = fields.Function(fields.Numeric(
            "Discount Rate", digits=(None, 4),
            states={
                'invisible': Eval('type') != 'line',
                'readonly': Eval('sale_state') != 'draft',
                }),
        'on_change_with_discount_rate', setter='set_discount_rate')
    discount_amount = fields.Function(Monetary(
            "Discount Amount", currency='currency', digits=price_digits,
            states={
                'invisible': Eval('type') != 'line',
                'readonly': Eval('sale_state') != 'draft',
                }),
        'on_change_with_discount_amount', setter='set_discount_amount')

    discount = fields.Function(fields.Char(
            "Discount",
            states={
                'invisible': ~Eval('discount'),
                }),
        'on_change_with_discount')

    @fields.depends(
        methods=[
            'compute_base_price', 'on_change_with_discount_rate',
            'on_change_with_discount_amount', 'on_change_with_discount'])
    def on_change_product(self):
        super().on_change_product()
        if self.product:
            self.base_price = self.compute_base_price()
            self.discount_rate = self.on_change_with_discount_rate()
            self.discount_amount = self.on_change_with_discount_amount()
            self.discount = self.on_change_with_discount()

    @fields.depends('product', 'unit')
    def compute_base_price(self):
        pool = Pool()
        Uom = pool.get('product.uom')
        if (self.product
                and (price := self.product.list_price_used) is not None):
            if self.unit:
                price = Uom.compute_price(
                    self.product.default_uom, price, self.unit)
            return round_price(price)

    @fields.depends(
        methods=[
            'compute_base_price', 'on_change_with_discount_rate',
            'on_change_with_discount_amount', 'on_change_with_discount'])
    def on_change_quantity(self):
        super().on_change_quantity()
        self.base_price = self.compute_base_price()
        self.discount_rate = self.on_change_with_discount_rate()
        self.discount_amount = self.on_change_with_discount_amount()
        self.discount = self.on_change_with_discount()

    @fields.depends('unit_price', 'base_price')
    def on_change_with_discount_rate(self, name=None):
        if self.unit_price is None or not self.base_price:
            return
        rate = 1 - self.unit_price / self.base_price
        return rate.quantize(
            Decimal(1) / 10 ** self.__class__.discount_rate.digits[1])

    @fields.depends(
        'base_price', 'discount_rate',
        methods=['on_change_with_discount_amount', 'on_change_with_discount',
            'on_change_with_amount'])
    def on_change_discount_rate(self):
        if self.base_price is not None and self.discount_rate is not None:
            self.unit_price = round_price(
                self.base_price * (1 - self.discount_rate))
            self.discount_amount = self.on_change_with_discount_amount()
            self.discount = self.on_change_with_discount()
            self.amount = self.on_change_with_amount()

    @classmethod
    def set_discount_rate(cls, lines, name, value):
        pass

    @fields.depends('unit_price', 'base_price')
    def on_change_with_discount_amount(self, name=None):
        if self.unit_price is None or self.base_price is None:
            return
        return round_price(self.base_price - self.unit_price)

    @fields.depends(
        'base_price', 'discount_amount',
        methods=['on_change_with_discount_rate', 'on_change_with_discount',
            'on_change_with_amount'])
    def on_change_discount_amount(self):
        if self.base_price is not None and self.discount_amount is not None:
            self.unit_price = round_price(
                self.base_price - self.discount_amount)
            self.discount_rate = self.on_change_with_discount_rate()
            self.discount = self.on_change_with_discount()
            self.amount = self.on_change_with_amount()

    @classmethod
    def set_discount_amount(cls, lines, name, value):
        pass

    @fields.depends(
        'sale', '_parent_sale.currency',
        methods=[
            'on_change_with_discount_rate', 'on_change_with_discount_amount'])
    def on_change_with_discount(self, name=None):
        pool = Pool()
        Lang = pool.get('ir.lang')
        lang = Lang.get()
        rate = self.on_change_with_discount_rate()
        if not rate or rate % Decimal('0.01'):
            amount = self.on_change_with_discount_amount()
            if amount:
                if self.sale and self.sale.currency:
                    return lang.currency(
                        amount, self.sale.currency, digits=price_digits[1])
                else:
                    return lang.format_number(
                        amount, digits=price_digits[1], monetary=True)
        else:
            return lang.format('%i', rate * 100) + '%'

    @classmethod
    def view_attributes(cls):
        return super().view_attributes() + [
            ('/form//label[@id="discount"]', 'states', {
                'invisible': Eval('type') != 'line',
                }, ['type']),
            ]
