# Copyright 2016-2019 Akretion (http://www.akretion.com/)
# Copyright 2020 Criptomart <tech@criptomart.net>
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# @author Santi Noreña (<santi@criptomart.net>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

import logging

from odoo import models
from odoo.tools import float_compare
from odoo.tools import float_is_zero
from odoo.tools import float_round

_logger = logging.getLogger(__name__)


class StockMove(models.Model):
    _inherit = "stock.move"

    def product_price_update_before_done(self):
        res = super().product_price_update_before_done()
        for move in self.filtered(lambda move: move.location_id.usage == "supplier"):
            if (
                move.product_id.last_purchase_price_compute_type
                == "with_three_discounts"
            ):
                price_updated = float_round(
                    move.purchase_line_id.price_subtotal
                    / move.purchase_line_id.product_qty,
                    precision_digits=2,
                )
            elif move.product_id.last_purchase_price_compute_type == "with_discount":
                price_updated = float_round(
                    move.purchase_line_id.price_unit
                    * (1 - move.purchase_line_id.discount1 / 100),
                    precision_digits=2,
                )
            elif (
                move.product_id.last_purchase_price_compute_type == "with_two_discounts"
            ):
                price_updated = float_round(
                    move.purchase_line_id.price_unit
                    * (1 - move.purchase_line_id.discount1 / 100)
                    * (1 - move.purchase_line_id.discount2 / 100),
                    precision_digits=2,
                )
            else:
                price_updated = move.purchase_line_id.price_unit

            # Convert price to product's base UoM if purchase UoM is different
            if (
                move.purchase_line_id
                and move.purchase_line_id.product_uom != move.product_id.uom_id
            ):
                price_updated = move.purchase_line_id.product_uom._compute_price(
                    price_updated, move.product_id.uom_id
                )

            _logger.info(
                "[PRICE DEBUG] Product %s [%s]: price_updated=%.2f, current_price=%.2f, quantity=%.2f, will_update=%s",
                move.product_id.default_code or move.product_id.name,
                move.product_id.id,
                price_updated,
                move.product_id.last_purchase_price_received,
                move.quantity,
                bool(
                    float_compare(
                        move.product_id.last_purchase_price_received,
                        price_updated,
                        precision_digits=2,
                    )
                    and not float_is_zero(move.quantity, precision_digits=3)
                ),
            )

            if float_compare(
                move.product_id.last_purchase_price_received,
                price_updated,
                precision_digits=2,
            ) and not float_is_zero(move.quantity, precision_digits=3):
                _logger.info(
                    "[PRICE] Product %s [%s]: Purchase price updated from %.2f to %.2f (Move: %s, PO: %s, compute_type: %s)",
                    move.product_id.default_code or move.product_id.name,
                    move.product_id.id,
                    move.product_id.last_purchase_price_received,
                    price_updated,
                    move.name,
                    (
                        move.purchase_line_id.order_id.name
                        if move.purchase_line_id
                        else "N/A"
                    ),
                    move.product_id.last_purchase_price_compute_type,
                )
                # Use write() to ensure value is persisted before computing price
                product_company = move.product_id.with_company(move.company_id)
                product_company.write(
                    {
                        "last_purchase_price_received": price_updated,
                    }
                )
                # Verify write was successful
                product_company.invalidate_recordset()
                _logger.info(
                    "[PRICE DEBUG] Product %s [%s]: After write, last_purchase_price_received=%.2f",
                    product_company.default_code or product_company.name,
                    product_company.id,
                    product_company.last_purchase_price_received,
                )
                product_company._compute_theoritical_price()
        return res
