from odoo import models, _


class SaleOrder(models.Model):
    _name = 'sale.order'
    _inherit = ['account.external.tax.mixin', 'sale.order']

    def _get_external_tax_totals(self, amount_total, amount_untaxed, amount_tax):
        tax_totals = self.tax_totals
        subtotal = tax_totals['subtotals'] and tax_totals['subtotals'][0] or {}
        tax_totals['same_tax_base'] = True
        tax_totals['total_amount_currency'] = amount_total
        tax_totals['base_amount_currency'] = amount_untaxed
        tax_totals['tax_amount_currency'] = amount_tax
        tax_totals['subtotals'] = [
            {
                **subtotal,
                'base_amount_currency': tax_totals['base_amount_currency'],
                'tax_amount_currency': tax_totals['tax_amount_currency'],
                'tax_groups': [],
            }
        ]
        if subtotal.get('tax_groups'):
            tax_group = subtotal['tax_groups'][0]
            tax_totals['subtotals'][0]['tax_groups'].append({
                **tax_group,
                'group_name': _('Taxes'),
                'base_amount_currency': tax_totals['base_amount_currency'],
                'tax_amount_currency': tax_totals['tax_amount_currency'],
            })
        return tax_totals

    def _compute_tax_totals(self):

        super()._compute_tax_totals()
        for order in self.filtered('is_tax_computed_externally'):
            order.tax_totals = order._get_external_tax_totals(order.amount_total, order.amount_untaxed, order.amount_tax)

    def _compute_amounts(self):

        external_tax_orders = self.filtered('is_tax_computed_externally')
        for order in external_tax_orders:
            order_lines = order.order_line.filtered(lambda x: not x.display_type)
            order.amount_untaxed = sum(order_lines.mapped('price_subtotal'))
            order.amount_tax = sum(order_lines.mapped('price_tax'))
            order.amount_total = order.amount_untaxed + order.amount_tax
        super(SaleOrder, self - external_tax_orders)._compute_amounts()

    def _create_account_invoices(self, invoice_vals_list, final):

        moves = super()._create_account_invoices(invoice_vals_list, final)
        if final:  # Don't needlessly do this for non-final invoices.
            moves.filtered(lambda move: any(move.line_ids.sale_line_ids.mapped('is_downpayment')))._get_and_set_external_taxes_on_eligible_records()
        return moves

    def action_confirm(self):
        self._get_and_set_external_taxes_on_eligible_records()
        return super().action_confirm()

    def action_quotation_send(self):
        self._get_and_set_external_taxes_on_eligible_records()
        return super().action_quotation_send()

    def _get_and_set_external_taxes_on_eligible_records(self):
        eligible_orders = self.filtered(lambda order: order.is_tax_computed_externally and order.state in ('draft', 'sent', 'sale') and not order.locked)
        eligible_orders._set_external_taxes(*eligible_orders._get_external_taxes())
        return super()._get_and_set_external_taxes_on_eligible_records()

    def _get_lines_eligible_for_external_taxes(self):
        return self.order_line.filtered(lambda l: not l.display_type and not l.is_downpayment)

    def _get_line_data_for_external_taxes(self):
        res = []
        for line in self._get_lines_eligible_for_external_taxes():

            line.tax_id = False

            res.append({
                "id": line.id,
                "model_name": line._name,
                "product_id": line.product_id,
                "qty": line.product_uom_qty,
                "price_subtotal": line.price_subtotal,
                "price_unit": line.price_unit,
                "discount": line.discount,
                "is_refund": False,
            })

        return res

    def _set_external_taxes(self, mapped_taxes, summary):
        """ account.external.tax.mixin override. """
        to_flush = self.env['sale.order.line']
        for line, detail in mapped_taxes.items():
            line.tax_id = detail['tax_ids']
            to_flush += line

        to_flush.flush_recordset(['price_tax', 'price_subtotal', 'price_total'])

        for line, detail in mapped_taxes.items():
            line.price_tax = detail['tax_amount']
            line.price_subtotal = detail['total']
            line.price_total = detail['tax_amount'] + detail['total']

    def _get_date_for_external_taxes(self):
        return self.date_order


class SaleOrderLine(models.Model):
    _inherit = 'sale.order.line'

    def _prepare_invoice_line(self, **optional_values):

        res = super()._prepare_invoice_line(**optional_values)

        if self.order_id.is_tax_computed_externally:
            res['tax_ids'] = False

        return res
