# Copyright 2017 Camptocamp SA
# Copyright 2019 Tecnativa
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

from odoo import api, fields, models
from collections import OrderedDict


class ProductProduct(models.Model):
    _inherit = 'product.product'

    auto_orderpoint_template_ids = fields.Many2many(
        comodel_name='stock.warehouse.orderpoint.template',
        string="Automatic Reordering Rules",
        domain=[('auto_generate', '=', True)],
        help="When one or several automatic reordering rule is selected, "
             "a Scheduled Action will automatically generate or update "
             "the reordering rules of the product."
    )

    @api.model
    def create(self, vals):
        record = super().create(vals)
        if vals.get('auto_orderpoint_template_ids'):
            record.auto_orderpoint_template_ids.create_orderpoints(record)
        return record

    @api.multi
    def write(self, vals):
        result = super().write(vals)
        if vals.get('auto_orderpoint_template_ids'):
            orderpoint_templates = self.mapped('auto_orderpoint_template_ids')
            orderpoint_templates.create_orderpoints(self)
        return result

    def _compute_historic_quantities_dict(
            self, location_id=False, from_date=False, to_date=False):
        """Returns a dict of products with a dict of historic moves as for
           a list of historic stock values resulting from those moves. If
           a location_id is passed, we can restrict it to such location"""
        location = location_id and location_id.id
        domain_quant_loc, domain_move_in_loc, domain_move_out_loc = (
            self.with_context(location=location)._get_domain_locations())
        if not to_date:
            to_date = fields.Datetime.now()
        domain_move_in = domain_move_out = ([
            ('product_id', 'in', self.ids),
            ('state', '=', 'done'),
        ] + domain_move_in_loc)
        domain_move_out = ([
            ('product_id', 'in', self.ids),
            ('state', '=', 'done'),
        ] + domain_move_out_loc)
        if from_date:
            domain_move_in += [('date', '>=', from_date)]
            domain_move_out += [('date', '>=', from_date)]
        domain_move_in += [('date', '<=', to_date)]
        domain_move_out += [('date', '<=', to_date)]
        move_obj = self.env['stock.move']
        # Positive moves
        moves_in = move_obj.search_read(
            domain_move_in, ['product_id', 'product_qty', 'date'],
            order='date asc')
        # We'll convert to negative these quantities to operate with them
        # to obtain the stock snapshot in every moment
        moves_out = move_obj.search_read(
            domain_move_out, ['product_id', 'product_qty', 'date'],
            order='date asc')
        for move in moves_out:
            move['product_qty'] *= -1
        # Merge both results and group them by product id as key
        moves = moves_in + moves_out
        # Obtain a dict with the stock snapshot for the relative date_from
        # otherwise, the first move will counted as first stock value. We
        # default the compute the stock value anyway to default the value
        # for products with no moves for the given period
        initial_stock = {}
        initial_stock = self.with_context(
            location=location)._compute_quantities_dict(
                False, False, False, to_date=from_date or to_date)
        product_moves_dict = {}
        for move in moves:
            product_moves_dict.setdefault(move['product_id'][0], {})
            product_moves_dict[move['product_id'][0]].update({
                move['date']: {
                    'prod_qty': move['product_qty'],
                }
            })
        for product in self.with_context(prefetch_fields=False):
            # If no there are no moves for a product we default the stock
            # to the one for the given period nevermind the dates
            product_moves = product_moves_dict.get(product.id)
            prod_initial_stock = initial_stock.get(product.id, {})
            if not product_moves:
                product_moves_dict[product.id] = {
                    to_date: {
                        'prod_qty': 0,
                        'stock': prod_initial_stock.get('qty_available', 0),
                    },
                    'stock_history': [
                        prod_initial_stock.get('qty_available', 0)],
                }
                continue
            # Now we'll sort the moves by date and assign an initial stock so
            # we can compute the stock historical values from the moves
            # sequence so we can exploit it statisticaly
            product_moves = OrderedDict(sorted(product_moves.items()))
            stock = False
            first_item = product_moves[next(iter(product_moves))]
            if from_date:
                stock = prod_initial_stock.get('qty_available')
            if not stock:
                stock = first_item['prod_qty']
            first_item['stock'] = stock
            iter_moves = iter(product_moves)
            next(iter_moves, None)
            for date in iter_moves:
                stock += product_moves[date]['prod_qty']
                product_moves[date]['stock'] = stock
            product_moves_dict[product.id]['stock_history'] = (
                [v['stock'] for k, v in product_moves.items()])
        return product_moves_dict
