# Author Mufti Muntasir Ahmed 20-06-2021

from odoo import fields, models, _
import datetime
from datetime import datetime
from odoo.osv import osv


class ManifestOutbound(models.Model):
    _name = "manifest.outbound"
    _description = "Manifest Process Outbound"
    _order = 'id desc'

    name = fields.Char('Order Number', required=True)
    customer_name = fields.Char('Customer Name')
    scan = fields.Char('Scan')
    outbound_line = fields.One2many('manifest.outbound.line', 'manifest_outbound_id', 'Outbound Line',
                                    required=True)
    confirm = fields.Boolean('Confirm')
    confirm_by = fields.Many2one('res.users', 'Confirm By')
    cancel = fields.Boolean('Cancel')
    cancel_by = fields.Many2one('res.users', 'Cancel By')
    has_return = fields.Boolean('Has Return')
    delivered = fields.Boolean('Delivered')
    stock_return_id = fields.Integer('Stock Return ID')
    invoice_return_id = fields.Integer('Invoice Return ID')
    delivery_date = fields.Date('Delivery Date', required=True)
    state = fields.Selection([
        ('pending', 'Pending'),
        ('confirm', 'Confirmation'),
        ('cancel', 'Cancelled'),
    ], 'Status', readonly=True, copy=False, help="Gives the status of the Mainfest", index=True)
    man_name = fields.Char('Manifest No')
    delivery_time = fields.Char('Delivery Time')
    source = fields.Char('Source')
    delivery_done_by = fields.Many2one('res.users', 'Delivered Done By')
    delivery_done_datetime = fields.Datetime('Delivered Done Date')

    def create(self, vals):

        order_number = None
        today_date = datetime.date.today()

        has_return = False
        inv_id = None
        for items in vals.get('outbound_line'):
            if items:
                for items2 in items:
                    if isinstance(items2, dict):
                        inv_id = items2.get('invoice_id')
                        order_number = items2.get('magento_no')
                        if float(items2.get('quantity')) > float(items2.get('delivered')):
                            items2['return_qty'] = str(float(items2.get('quantity')) - float(items2.get('delivered')))
                            has_return = True
                        else:
                            items2['return_qty'] = '0.00'

                        today_date = items2.get('delivery_date')

        vals['has_return'] = has_return
        vals['name'] = order_number
        vals['state'] = 'pending'
        today_date = vals.get('delivery_date')

        inv_data = self.env['account.invoice'].browse([inv_id])
        if inv_data:
            if inv_data.delivered:
                raise osv.except_osv(_('Already Assigned!'), _('This Order Already Delivered'))
        # if context is None:
        #     context = {}

        section_id = super(ManifestOutbound, self).create(vals)

        self.env.cr.execute("update account_invoice set delivery_date=%s,delivered=TRUE where id=%s",
                            ([today_date, inv_id]))

        self.env.cr.commit()

        if order_number is not None:
            self.env.cr.execute("select id from  sale_order where client_order_ref=%s", ([str(order_number)]))
            abc = self.env.cr.fetchall()
            sale_ids = [abc[0][0]]

            sales = self.env['sale.order'].browse(sale_ids)[0]

            if sales.delivered_amount == sales.amount_total:
                self.env.cr.execute("update sale_order set delivery_dispatch=TRUE where id=%s", ([sales.id]))
                self.env.cr.commit()
                self.env.cr.execute("update sale_order set partially_invoiced_dispatch=FALSE where id=%s", ([sales.id]))
                self.env.cr.commit()
            elif sales.delivered_amount < sales.amount_total and sales.delivered_amount > 0:
                self.env.cr.execute("update sale_order set partially_invoiced_dispatch=TRUE where id=%s", ([sales.id]))
                self.env.cr.commit()

        self.env.cr.commit()
        return section_id

    def receipt_return_stock(self):
        try:
            stock_picking_name = None
            invoice_name = None
            return_list = self.env['manifest.outbound'].browse()[0]

            if return_list.stock_return_id:
                raise osv.except_osv(_('Already Received!'), _('Already Received'))

            self.env.cr.execute("select invoice_id from  manifest_outbound_line where manifest_outbound_id=%s", (self.ids))

            invoice_ids = self.env.cr.fetchall()

            new_inv_ids = [items[0] for items in invoice_ids]

            if len(new_inv_ids) > 0:
                invoice_id = new_inv_ids[0]

                self.env.cr.execute("select origin,number from  account_invoice where id=%s", ([invoice_id]))
                origin = self.env.cr.fetchall()

                for item in origin:
                    if item:
                        stock_picking_name = item[0]
                        invoice_name = item[1]

            self.env.cr.execute("select id from  stock_picking where name=%s", ([stock_picking_name]))

            stock_id_lists = [items[0] for items in self.env.cr.fetchall()]
            stock_object = self.env['stock.picking'].browse(stock_id_lists)[0]

            product_dict = {}
            product_return_moves = [[5, False, False]]
            for items in return_list.outbound_line:

                if items.quantity > items.delivered:
                    product_dict = {}
                    product_dict['product_id'] = items.product_id
                    product_dict['quantity'] = items.quantity - items.delivered
                    product_dict['lot_id'] = False

                    for st_items in stock_object.move_lines:
                        if st_items.product_id.id == items.product_id:
                            product_dict['move_id'] = st_items.id
                            product_return_moves.append([0, False, product_dict])
                            product_dict = {}

            prepare_data = {'product_return_moves': product_return_moves,
                            'invoice_state': '2binvoiced'}

            return_pool = self.env['stock.return.picking']
            data = prepare_data

            values = prepare_data
            self.context.update({
                'active_model': 'stock.picking',
                'active_ids': [stock_object.id],
                'active_id': stock_object.id,
                'refund': True
            })

            created_id = self.env['stock.return.picking'].create(values)

            return_stock_id = None
            return_inv_id = None

            id_list = [created_id]
            self.context['active_id'] = stock_object.id
            stock_picking_id = return_pool._create_returns(id_list)
            # 2 id is coming

            # cr.commit()
            try:

                if stock_picking_id:
                    return_stock_id = stock_picking_id[0]

                    # Stock Transfer Starts from Here
                    picking = [stock_picking_id[0]]

                    self.context.update({

                        'active_model': 'stock.picking',
                        'active_ids': picking,
                        'active_id': len(picking) and picking[0] or False
                    })

                    stock_transfer_created_id = self.env['stock.transfer_details'].create({
                        'picking_id': len(picking) and picking[0] or False})

                    if stock_transfer_created_id:
                        stock_transfer_id = self.env['stock.transfer_details'].browse(stock_transfer_created_id)
                        if stock_transfer_id.picking_id.state in ['assigned', 'partially_available']:
                            # raise Warning(_('You cannot transfer a picking in state \'%s\'.') % created_id.picking_id.state)

                            processed_ids = []
                            # Create new and update existing pack operations
                            for lstits in [stock_transfer_id.item_ids, stock_transfer_id.packop_ids]:
                                for prod in lstits:
                                    pack_datas = {
                                        'product_id': prod.product_id.id,
                                        'product_uom_id': prod.product_uom_id.id,
                                        'product_qty': prod.quantity,
                                        'package_id': prod.package_id.id,
                                        'lot_id': prod.lot_id.id,
                                        'location_id': prod.sourceloc_id.id,
                                        'location_dest_id': prod.destinationloc_id.id,
                                        'result_package_id': prod.result_package_id.id,
                                        'date': prod.date if prod.date else datetime.now(),
                                        'owner_id': prod.owner_id.id,
                                    }
                                    if prod.packop_id:
                                        prod.packop_id.with_context(no_recompute=True).write(pack_datas)
                                        processed_ids.append(prod.packop_id.id)
                                    else:
                                        pack_datas['picking_id'] = stock_transfer_id.picking_id.id
                                        packop_id = stock_transfer_id.env['stock.pack.operation'].create(pack_datas)
                                        processed_ids.append(packop_id.id)
                            # Delete the others
                            packops = stock_transfer_id.env['stock.pack.operation'].search(
                                ['&', ('picking_id', '=', stock_transfer_id.picking_id.id), '!',
                                 ('id', 'in', processed_ids)])
                            packops.unlink()

                            # Execute the transfer of the picking
                            stock_transfer_id.picking_id.do_transfer()

                            # Stock Transfer End Here

                        # Invoice start Here

                        if stock_transfer_id.picking_id.invoice_state != 'invoiced' and stock_transfer_id.picking_id.state == 'done':
                            # Now Create the Invoice for this picking
                            res = []
                            picking_pool = self.env['stock.picking']
                            from datetime import date
                            self.context['date_inv'] = date.today()
                            self.context['inv_type'] = 'in_invoice'
                            active_ids = [stock_picking_id[0]]

                            stock_invoice_onshipping_data = {
                                'journal_id': 1147,
                                'journal_type': 'sale_refund',
                                'invoice_date': date.today(),
                                'invoice_number': invoice_name
                            }

                            stock_invoice_onshipping_obj = self.env["stock.invoice.onshipping"]
                            stock_invoice_onshipping_id = stock_invoice_onshipping_obj.create(stock_invoice_onshipping_data,)

                            res = stock_invoice_onshipping_obj.open_invoice([stock_invoice_onshipping_id])

                            return_inv_id = res if res else None

                        else:
                            raise osv.except_osv(_('Warning!'),
                                                 _('Something wrong!!.Please check your return move is create or not'))
            except:
                raise osv.except_osv(_('Error!'), _('Something wrong!!.'))

            stock_return_id = return_stock_id
            invoice_return_id = return_inv_id

            # cr.commit()
            for id in self.ids:
                self.env.cr.execute("update manifest_outbound set invoice_return_id=%s,stock_return_id=%s,state='confirm',"
                           "confirm_by=%s,confirm=TRUE where id=%s",
                           ([invoice_return_id, stock_return_id, id]))
                self.env.cr.commit()

                self.env.cr.execute(
                    "update manifest_outbound_line set invoice_return_id=%s where manifest_outbound_id=%s",
                    ([invoice_return_id, id]))

                self.env.cr.commit()

            # Dispatch Delivered Flag update
        except:
            raise osv.except_osv(_('Error!'), _('Something wrong!!.'))

        return True


class ManifestOutboundLine(models.Model):
    _name = "manifest.outbound.line"
    _description = "Manifest Outbound Line"

    manifest_outbound_id = fields.Many2one('manifest.outbound', 'Manifest Outbound Line ID', required=True,
                                                ondelete='cascade', index=True, readonly=True)
    invoice_id = fields.Integer('Invoice ID', readonly=True)
    magento_no = fields.Char('Order No', readonly=True)
    description = fields.Char('Description', readonly=True)
    product_id = fields.Integer('Product ID', readonly=True)
    amount = fields.Float('Amount', readonly=True)
    quantity = fields.Float('Quantity', readonly=True)
    delivered = fields.Float('Delivered')
    return_qty = fields.Float('Return', readonly=True)
    invoice_return_id = fields.Integer('Invoice Return ID')

    # delivered amount
    def _get_delivered_amount(self):
        res = False
        # res = {}
        #
        # for manifest_process_line in self.browse():
        #
        #     total_sum = ''
        #     inv_id = manifest_process_line.invoice_id
        #     self.env.cr.execute("select name from  account_invoice where id=%s", ([inv_id]))
        #
        #     invoice_ids_obj = self.env.cr.fetchall()
        #     if len(invoice_ids_obj) > 0:
        #         total_sum = invoice_ids_obj[0]
        #
        #     res[manifest_process_line.id] = total_sum
        return res

    def _get_return_amount_fnc(self):
        res = {}

        """
        for partner in self.browse(cr, uid, ids, context=context):
            res[partner.id] = self._display_address(cr, uid, partner, context=context)
        """

        return res

    return_reason = fields.Char('Return Reason')

