# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo import fields, models, api, _


class AccountMove(models.Model):
    _name = 'account.move'
    _inherit = ['account.move', 'pos.load.mixin']

    pos_order_ids = fields.One2many('pos.order', 'account_move')
    pos_payment_ids = fields.One2many('pos.payment', 'account_move_id')
    pos_refunded_invoice_ids = fields.Many2many('account.move', 'refunded_invoices', 'refund_account_move', 'original_account_move')
    reversed_pos_order_id = fields.Many2one('pos.order', string="Reversed POS Order",
        index='btree_not_null',
        help="The pos order that was reverted after closing the session to create an invoice for it.")
    pos_session_ids = fields.One2many("pos.session", "move_id", "POS Sessions")
    pos_order_count = fields.Integer(compute="_compute_origin_pos_count", string='POS Order Count')

    @api.depends('pos_order_ids')
    def _compute_origin_pos_count(self):
        for move in self:
            move.pos_order_count = len(move.sudo().pos_order_ids)

    @api.depends('tax_cash_basis_created_move_ids', 'pos_session_ids')
    def _compute_always_tax_exigible(self):
        super()._compute_always_tax_exigible()
        # The pos closing move does not create caba entries (anymore); we set the tax values directly on the closing move.
        # (But there may still be old closing moves that used caba entries from previous versions.)
        for move in self:
            if move.always_tax_exigible or move.tax_cash_basis_created_move_ids:
                continue
            if move.pos_session_ids:
                move.always_tax_exigible = True


    def _get_invoiced_lot_values(self):
        self.ensure_one()

        lot_values = super(AccountMove, self)._get_invoiced_lot_values()

        if self.state == 'draft':
            return lot_values

        # user may not have access to POS orders, but it's ok if they have
        # access to the invoice
        for order in self.sudo().pos_order_ids:
            for line in order.lines:
                lots = line.pack_lot_ids or False
                if lots:
                    for lot in lots:
                        stock_lot = self._get_stock_lot_from_pos_lot(lot)
                        lot_values.append({
                            'product_name': lot.product_id.name,
                            'quantity': line.qty if lot.product_id.tracking == 'lot' else 1.0,
                            'uom_name': line.product_uom_id.name,
                            'lot_name': lot.lot_name,
                            'pos_lot_id': lot.id,
                            'lot_id': stock_lot.id,
                        } | (self._extract_extra_invoiced_lot_values(stock_lot) if stock_lot else {}))

        return lot_values

    def _get_stock_lot_from_pos_lot(self, pos_lot):
        """Return the stock lot matching a POS lot name.

        POS order lines store lot/serial numbers in ``pos.pack.operation.lot``.
        Extra invoice lot values, however, are computed from ``stock.lot``.
        """
        self.ensure_one()
        pos_lot.ensure_one()

        if not pos_lot.lot_name:
            return self.env['stock.lot']
        company = pos_lot.order_id.company_id or self.company_id
        return self.env['stock.lot'].sudo().search([
            '|', ('company_id', '=', False), ('company_id', '=', company.id),
            ('product_id', '=', pos_lot.product_id.id),
            ('name', '=', pos_lot.lot_name),
        ], limit=1)

    def _prepare_payments_widget_reconciled_info(self, partial_info):
        # EXTENDS account.
        results = super()._prepare_payments_widget_reconciled_info(partial_info)
        counterpart_line = partial_info['aml']
        results['pos_payment_name'] = counterpart_line.move_id.sudo().pos_payment_ids[:1].payment_method_id.name
        return results

    def _compute_amount(self):
        super()._compute_amount()
        for move in self:
            if move.move_type == 'entry' and move.reversed_pos_order_id:
                move.amount_total_signed = move.amount_total_signed * -1

    def _compute_tax_totals(self):
        return super(AccountMove, self.with_context(linked_to_pos=bool(self.sudo().pos_order_ids)))._compute_tax_totals()

    def _compute_is_storno(self):
        # EXTENDS 'account'
        super()._compute_is_storno()
        for move in self:
            move.is_storno = move.is_storno or (
                move.company_id.account_storno and move.reversed_pos_order_id
            )

    def action_view_source_pos_orders(self):
        self.ensure_one()
        action = self.env['ir.actions.act_window']._for_xml_id('point_of_sale.action_pos_pos_form')

        if len(self.pos_order_ids) == 1:
            action['views'] = [(self.env.ref('point_of_sale.view_pos_pos_form', False).id, 'form')]
            action['res_id'] = self.pos_order_ids.id
        else:
            action['domain'] = [('id', 'in', self.pos_order_ids.ids)]
        return action

    def button_draft(self):
        if self.sudo().pos_order_ids.filtered(lambda o: o.session_id.state != 'closed'):
            self.env.user._bus_send("simple_notification", {
                'type': 'danger',
                'message': _("You can't reset this invoice to draft because the POS session is still open. Please close the ongoing session first, then try again."),
                'sticky': True,
            })
            return False
        return super().button_draft()

    @api.model
    def _load_pos_data_fields(self, config):
        result = super()._load_pos_data_fields(config)
        return result or ['id', 'name']

    @api.model
    def _load_pos_data_domain(self, data, config):
        return False

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

    def _get_cogs_value(self):
        self.ensure_one()
        if not self.product_id:
            return self.price_unit
        price_unit = super()._get_cogs_value()
        sudo_order = self.move_id.sudo().pos_order_ids
        if sudo_order:
            price_unit = sudo_order._get_pos_anglo_saxon_price_unit(self.product_id, self.move_id.partner_id.id, self.quantity)
        return price_unit

    def _compute_name(self):
        amls = self.filtered(lambda l: not l.move_id.pos_session_ids)
        super(AccountMoveLine, amls)._compute_name()
