# -*- coding: utf-8 -*-

from odoo import models, fields, api, _
from odoo.exceptions import UserError
from collections import defaultdict


class FusionPurchaseOrderWiz(models.TransientModel):
    _name = 'fusion.so.po.wiz'
    _description = 'Fusion - Create Purchase Order Wizard'

    fusion_so_id = fields.Many2one('sale.order', string='Sale Order')
    fusion_line_ids = fields.One2many(
        'fusion.so.po.line.wiz',
        'fusion_wizard_id',
        string='Products',
    )
    fusion_batch_vendor_id = fields.Many2one(
        'res.partner',
        string='Assign Vendor to All',
        domain="[('is_company', '=', True)]",
        help='Select a vendor here to assign it to ALL products at once',
    )

    @api.onchange('fusion_batch_vendor_id')
    def _onchange_fusion_batch_vendor_id(self):
        if self.fusion_batch_vendor_id:
            selected_lines = self.fusion_line_ids.filtered(lambda l: l.selected)
            lines_to_update = selected_lines if selected_lines else self.fusion_line_ids

            for line in lines_to_update:
                line.vendor_id = self.fusion_batch_vendor_id
                if line.product_id:
                    seller = line.product_id.seller_ids.filtered(
                        lambda s: s.partner_id.id == self.fusion_batch_vendor_id.id
                    )[:1]
                    if seller and seller.price:
                        line.price_unit = seller.price
                    else:
                        line.price_unit = line.product_id.standard_price
                    line.price_subtotal = line.price_unit * line.product_uom_qty

            for line in selected_lines:
                line.selected = False

    @api.model
    def default_get(self, fields_list):
        res = super().default_get(fields_list)
        active_ids = self._context.get('active_ids')
        if not active_ids:
            return res

        sale_order = self.env['sale.order'].browse(active_ids[0])
        if not sale_order.order_line:
            raise UserError(_("Please add some valid sale order lines...!"))

        res['fusion_so_id'] = sale_order.id

        product_lines = []
        for line in sale_order.order_line:
            if line.display_type in ('line_section', 'line_note'):
                continue

            description = line.name or line.product_id.display_name or line.product_id.name or 'Product'

            cost_price = line.product_id.standard_price
            product_lines.append((0, 0, {
                'product_id': line.product_id.id,
                'description': description,
                'product_uom_qty': line.product_uom_qty,
                'price_unit': cost_price,
                'product_uom': line.product_uom_id.id,
                'price_subtotal': cost_price * line.product_uom_qty,
                'fusion_so_line_id': line.id,
                'vendor_id': False,
            }))

        res['fusion_line_ids'] = product_lines
        return res

    def fusion_create_po(self):
        self.ensure_one()

        vendor_products = defaultdict(list)
        for product_line in self.fusion_line_ids:
            if product_line.vendor_id:
                vendor_products[product_line.vendor_id.id].append(product_line)

        if not vendor_products:
            raise UserError(_("Please assign at least one product to a vendor before creating Purchase Orders."))

        now = fields.Datetime.now()
        created_pos = self.env['purchase.order']
        customer = self.fusion_so_id.partner_id

        for vendor_id, product_lines in vendor_products.items():
            partner = self.env['res.partner'].browse(vendor_id)
            fpos = self.env['account.fiscal.position'].sudo()._get_fiscal_position(partner)

            date_planned = self.fusion_so_id.commitment_date or now

            purchase_order = self.env['purchase.order'].create({
                'partner_id': partner.id,
                'partner_ref': partner.ref,
                'company_id': self.fusion_so_id.company_id.id,
                'currency_id': self.env.company.currency_id.id,
                'dest_address_id': False,
                'origin': self.fusion_so_id.name,
                'payment_term_id': partner.property_supplier_payment_term_id.id,
                'date_order': now,
                'fiscal_position_id': fpos.id,
                'fusion_sale_ids': [(4, self.fusion_so_id.id)],
                'fusion_marked_for_ids': [(4, customer.id)],
            })

            for product_line in product_lines:
                values = product_line._prepare_fusion_po_line(purchase_order, date_planned)
                self.env['purchase.order.line'].create(values)

            created_pos |= purchase_order

        if len(created_pos) == 1:
            return {
                'name': _('Purchase Order'),
                'view_mode': 'form',
                'res_model': 'purchase.order',
                'view_id': self.env.ref('purchase.purchase_order_form').id,
                'res_id': created_pos.id,
                'type': 'ir.actions.act_window',
                'target': 'current',
            }
        return {
            'name': _('Purchase Orders'),
            'view_mode': 'list,form',
            'res_model': 'purchase.order',
            'domain': [('id', 'in', created_pos.ids)],
            'type': 'ir.actions.act_window',
            'target': 'current',
        }


class FusionPurchaseProductWiz(models.TransientModel):
    _name = 'fusion.so.po.line.wiz'
    _description = 'Fusion - Purchase Product Wizard Line'

    fusion_wizard_id = fields.Many2one('fusion.so.po.wiz', string='Wizard', ondelete='cascade')
    selected = fields.Boolean(string='Select', default=False)
    fusion_so_line_id = fields.Many2one('sale.order.line', string='SO Line')
    product_id = fields.Many2one('product.product', string='Product')
    product_uom = fields.Many2one('uom.uom', string='Unit of Measure')
    description = fields.Char(string='Description')
    product_uom_qty = fields.Float(string='Quantity')
    price_unit = fields.Float(string='Unit Price')
    price_subtotal = fields.Float(string='Subtotal')
    vendor_id = fields.Many2one(
        'res.partner',
        string='Vendor',
        domain="[('is_company', '=', True)]",
    )

    @api.onchange('vendor_id')
    def _onchange_vendor_id(self):
        if self.vendor_id and self.product_id:
            seller = self.product_id.seller_ids.filtered(
                lambda s: s.partner_id.id == self.vendor_id.id
            )[:1]
            if seller and seller.price:
                self.price_unit = seller.price
            else:
                self.price_unit = self.product_id.standard_price
            self.price_subtotal = self.price_unit * self.product_uom_qty

    def _prepare_fusion_po_line(self, purchase_order, date_planned):
        self.ensure_one()
        product_uom = self.product_uom or self.product_id.uom_id

        name = self.description
        if not name:
            name = self.product_id.display_name or self.product_id.name or 'Product'
        if self.product_id.default_code and self.product_id.default_code not in name:
            name = '[%s] %s' % (self.product_id.default_code, name)

        return {
            'name': name,
            'product_qty': self.product_uom_qty,
            'product_id': self.product_id.id,
            'product_uom_id': product_uom.id,
            'price_unit': self.price_unit,
            'date_planned': date_planned,
            'order_id': purchase_order.id,
        }
