# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo import _, models
from odoo.exceptions import UserError


class StockPicking(models.Model):
    _inherit = 'stock.picking'

    def button_validate(self):
        res = super().button_validate()
        if res is not True:
            return res

        for picking in self:
            project = picking.project_id
            sale_order = project.sudo().reinvoiced_sale_order_id
            if not (sale_order and picking.picking_type_id.analytic_costs):
                continue
            reinvoicable_stock_moves = picking.move_ids.filtered(lambda m: m.product_id.expense_policy in {'sales_price', 'cost'})
            if not reinvoicable_stock_moves:
                continue
            # raise if the sale order is not currently open
            if sale_order.state in ('draft', 'sent'):
                raise UserError(_(
                    "The Sales Order %(order)s linked to the Project %(project)s must be"
                    " validated before validating the stock picking.",
                    order=sale_order.name,
                    project=project.name,
                ))
            elif sale_order.state == 'cancel':
                raise UserError(_(
                    "The Sales Order %(order)s linked to the Project %(project)s is cancelled."
                    " You cannot validate a stock picking on a cancelled Sales Order.",
                    order=sale_order.name,
                    project=project.name,
                ))
            elif sale_order.locked:
                raise UserError(_(
                    "The Sales Order %(order)s linked to the Project %(project)s is currently locked."
                    " You cannot validate a stock picking on a locked Sales Order."
                    " Please create a new SO linked to this Project.",
                    order=sale_order.name,
                    project=project.name,
                ))
            # Create SOLs in reinvoiced_sale_order_id with reinvoicable stock moves
            sale_line_values_to_create = []
            # Get last sequence SOL
            last_so_line = self.env['sale.order.line'].search_read(
                [('order_id', '=', sale_order.id)],
                ['sequence'], order='sequence desc', limit=1,
            )
            last_sequence = next((sol['sequence'] for sol in last_so_line), 100)

            for stock_move in reinvoicable_stock_moves:
                # Get price
                price = stock_move._sale_get_invoice_price(sale_order)
                # Create the sale lines in batch
                sale_line_values_to_create.append(stock_move._sale_prepare_sale_line_values(sale_order, price, last_sequence))
                last_sequence += 1
            self.env['sale.order.line'].with_context(skip_procurement=True).sudo().create(sale_line_values_to_create)
        return res
