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

from odoo import _, api, models
from odoo.fields import Domain
from odoo.http import request


class ResPartner(models.Model):
    _inherit = 'res.partner'

    @api.onchange('property_product_pricelist')
    def _onchange_property_product_pricelist(self):
        open_order = self.env['sale.order'].sudo().search([
            ('partner_id', '=', self._origin.id),
            ('pricelist_id', '=', self._origin.property_product_pricelist.id),
            ('pricelist_id', '!=', self.property_product_pricelist.id),
            ('website_id', '!=', False),
            ('state', '=', 'draft'),
        ], limit=1)

        if open_order:
            return {'warning': {
                'title': _('Open Sale Orders'),
                'message': _(
                    "This partner has an open cart. "
                    "Please note that the pricelist will not be updated on that cart. "
                    "Also, the cart might not be visible for the customer until you update the pricelist of that cart."
                ),
            }}

    def _get_current_partner(self, *, order_sudo=False, **kwargs):
        """ Override `portal` to get current partner from order_sudo if user is not signed up. """
        if order_sudo:
            return (
                (not order_sudo._is_anonymous_cart() and order_sudo.partner_id)
                or self.env['res.partner'] # Avoid returning public user's partner
            )
        return super()._get_current_partner(order_sudo=order_sudo, **kwargs)

    def _get_frontend_writable_fields(self):
        """ Override `portal` to make website whitelist fields writable in portal address. """
        frontend_writable_fields = super()._get_frontend_writable_fields()
        frontend_writable_fields.update(
            self.env['ir.model']._get('res.partner')._get_form_writable_fields().keys()
        )

        return frontend_writable_fields

    def _get_order_fiscal_position_recompute_domain(self):
        """Return a domain of sale orders for which we should recompute fiscal position after address update."""
        return Domain([
            ('state', '=', 'draft'),
            ('website_id', '!=', False),
            '|', ('partner_id', 'in', self.ids),
                 ('partner_shipping_id', 'in', self.ids),
        ])

    def write(self, vals):
        res = super().write(vals)
        if {'country_id', 'vat', 'zip'} & vals.keys() and self:
            # Recompute fiscal position for open website orders
            order_fpos_recompute_domain = self._get_order_fiscal_position_recompute_domain()
            if orders_sudo := self.env['sale.order'].sudo().search(order_fpos_recompute_domain):
                orders_by_fpos = orders_sudo.grouped('fiscal_position_id')
                self.env.add_to_compute(orders_sudo._fields['fiscal_position_id'], orders_sudo)
                if fpos_changed := orders_sudo.filtered(
                    lambda so: so not in orders_by_fpos.get(so.fiscal_position_id, []),
                ):
                    fpos_changed._recompute_taxes()
                    # other modules may extend the orders to recompute for
                    # non-draft orders (for ex. sale_subscription), we need
                    # to ensure to only recompute prices for draft orders
                    fpos_changed.filtered(lambda order: order.state == 'draft')._recompute_prices()
        return res
