# Copyright (C) 2019-Today: Odoo Community Association (OCA)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo import fields, models
from odoo.tools.float_utils import float_round


class StockMove(models.Model):
    _name = "stock.move"
    _inherit = [
        _name,
        "stock.invoice.state.mixin",
    ]

    def _get_price_unit_invoice(self, inv_type, partner, qty=1):
        """
        Gets price unit for invoice
        :param inv_type: str
        :param partner: res.partner
        :param qty: float
        :return: float
        """

        if inv_type in ("in_invoice", "in_refund"):
            price_unit = min(self.mapped("price_unit"))
        else:
            price_unit = max(self.mapped("price_unit"))

        if price_unit > 0.0:
            # Value informed by user should has preferency
            return price_unit

        product = self.mapped("product_id")
        product.ensure_one()
        sum(self.mapped("product_uom_qty"))
        product_uom = self.mapped("product_uom")
        company = fields.first(self).picking_id.company_id
        # Only in the cases the stock.move has linked to Sale or
        # Purchase Order it's possible use different Currencys
        # TODO: Should this module make possible by include field
        #  currency_id in Stock.picking?
        currency = company.currency_id
        pickings = self.mapped("picking_id")
        date_done = min(pickings.mapped("date_done"))

        if inv_type in ("in_invoice", "in_refund"):
            seller = product._select_seller(
                partner_id=partner, quantity=qty, date=date_done
            )
            if not seller:
                po_line_uom = self.mapped("product_uom") or product.uom_po_id
                price_unit = self.env["account.tax"]._fix_tax_included_price_company(
                    product.uom_id._compute_price(product.standard_price, po_line_uom),
                    product.supplier_taxes_id,
                    # TODO: Should inform taxes_ids in stock.move?
                    product.supplier_taxes_id,
                    fields.first(self).company_id,
                )
                price_unit = product.currency_id._convert(
                    price_unit, currency, company, date_done, False
                )
                result = float_round(
                    price_unit,
                    precision_digits=max(
                        currency.decimal_places,
                        self.env["decimal.precision"].precision_get("Product Price"),
                    ),
                )
            else:
                price_unit = self.env["account.tax"]._fix_tax_included_price_company(
                    seller.price,
                    product.supplier_taxes_id,
                    # TODO: Should inform taxes_ids in stock.move?
                    product.supplier_taxes_id,
                    fields.first(self).company_id,
                )
                price_unit = seller.currency_id._convert(
                    price_unit, currency, company, date_done, False
                )
                price_unit = float_round(
                    price_unit,
                    precision_digits=max(
                        currency.decimal_places,
                        self.env["decimal.precision"].precision_get("Product Price"),
                    ),
                )
                result = seller.product_uom._compute_price(price_unit, product_uom)

        else:
            # If partner given, search price in its sale pricelist
            fiscal_position = (
                self.env["account.fiscal.position"]
                .with_company(company)
                ._get_fiscal_position(partner)
            )

            if partner and partner.property_product_pricelist:
                price_unit = None
                pricelist_rule_id = (
                    partner.property_product_pricelist._get_product_rule(
                        product,
                        qty or 1.0,
                        uom=product_uom,
                        date=date_done,
                    )
                )
                pricelist_rule = self.env["product.pricelist.item"].browse(
                    pricelist_rule_id
                )
                price_unit = pricelist_rule._compute_price(
                    product,
                    qty,
                    product_uom,
                    date_done,
                    currency=currency,
                )

            else:
                price_unit = product.lst_price

            result = product._get_tax_included_unit_price(
                company,
                currency,
                date_done,
                "sale",
                fiscal_position=fiscal_position,
                product_price_unit=price_unit,
                product_currency=currency,
            )

        return result

    def _prepare_extra_move_vals(self, qty):
        """Copy invoice state for a new extra stock move"""
        values = super()._prepare_extra_move_vals(qty)
        values["invoice_state"] = self.invoice_state
        return values

    def _prepare_move_split_vals(self, uom_qty):
        """Copy invoice state for a new splitted stock move"""
        values = super()._prepare_move_split_vals(uom_qty)
        values["invoice_state"] = self.invoice_state
        return values
