# Copyright 2019-2024 Akretion France (http://www.akretion.com/)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).


from odoo import api, fields, models
from odoo.tools import float_is_zero


class AccountMoveLine(models.Model):
    _inherit = 'account.move.line'

    commission_result_id = fields.Many2one(
        'commission.result', string='Commission Result', check_company=True)
    commission_rule_id = fields.Many2one(
        'commission.rule', 'Matched Commission Rule', ondelete='restrict', check_company=True)
    commission_base = fields.Monetary('Commission Base', currency_field='company_currency_id')
    commission_rate = fields.Float('Commission Rate', digits='Commission Rate')
    commission_amount = fields.Monetary(
        string='Commission Amount', currency_field='company_currency_id',
        readonly=True, compute='_compute_commission_amount', store=True)
    # to display on commission line
    product_categ_id = fields.Many2one(
        related='product_id.product_tmpl_id.categ_id')

    @api.depends('commission_rate', 'commission_base')
    def _compute_commission_amount(self):
        for line in self:
            commission_amount = False
            if line.display_type == 'product':
                commission_amount = line.company_currency_id.round(
                    line.commission_rate * line.commission_base / 100.0)
            line.commission_amount = commission_amount

    def _match_commission_rule(self, rules):
        # commission rules are already in the right order
        self.ensure_one()
        for rule in rules:
            if rule['date_start'] and rule['date_start'] > self.date:
                continue
            if rule['date_end'] and rule['date_end'] < self.date:
                continue
            if rule['applied_on'] == '0_customer_product':
                if (
                        self.partner_id.id in
                        rule['partner_ids'] and
                        self.product_id.id in rule['product_ids']):
                    return rule
            elif rule['applied_on'] == '1_customer_product_category':
                if (
                        self.partner_id.id in
                        rule['partner_ids'] and
                        self.product_categ_id.id in rule['product_categ_ids']):
                    return rule
            elif rule['applied_on'] == '2_product':
                if self.product_id.id in rule['product_ids']:
                    return rule
            elif rule['applied_on'] == '3_product_category':
                if self.product_categ_id.id in rule['product_categ_ids']:
                    return rule
            elif rule['applied_on'] == '4_global':
                return rule
        return False

    def _prepare_commission_data(self, rule):
        self.ensure_one()
        rate_prec = self.env['decimal.precision'].precision_get('Commission Rate')
        lvals = {
            'commission_rule_id': rule['id'],
            # company currency
            # inherit this method to change the value below if you want to base on margin
            # or something else
            'commission_rate': rule['rate'],
            }
        if rule['base'] == 'margin':
            # What do we do if it's negative ? For the moment, it adds a negative commission line
            cost = 0
            if self.product_id and self.product_uom_id:
                # if the module account_invoice_margin from akretion/odoo-usability is installed
                if hasattr(self, 'margin_company_currency'):
                    cost = self.margin_company_currency
                else:
                    sign = self.move_id.move_type == 'out_refund' and -1 or 1
                    cost = self.product_id.standard_price * self.product_uom_id._compute_quantity(self.quantity, self.product_id.uom_id) * sign
            lvals['commission_base'] = self.balance * -1 - cost
        else:
            lvals['commission_base'] = self.balance * -1
        if float_is_zero(lvals['commission_rate'], precision_digits=rate_prec) or self.company_currency_id.is_zero(lvals['commission_base']):
            return False
        return lvals
