# Copyright 2016-19 ForgeFlow S.L. (https://www.forgeflow.com)
# Copyright 2016 Aleph Objects, Inc. (https://www.alephobjects.com/)
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).

from odoo import api, fields, models, _
from odoo.addons import decimal_precision as dp
from odoo.exceptions import UserError

from datetime import timedelta, date


class StockDemandEstimate(models.Model):
    _name = 'stock.demand.estimate'
    _description = 'Stock Demand Estimate Line'

    date_from = fields.Date(
        compute="_compute_dates",
        string="From (computed)",
        store=True
    )
    date_to = fields.Date(
        compute="_compute_dates",
        string="To (computed)",
        store=True,
    )
    manual_date_from = fields.Date(string="From")
    manual_date_to = fields.Date(string="To")
    manual_duration = fields.Integer(
        string="Duration",
        help="Duration (in days)",
        default=1,
    )
    duration = fields.Integer(
        compute="_compute_dates",
        string="Duration (computed))",
        store=True,
    )
    product_id = fields.Many2one(
        comodel_name="product.product",
        string="Product",
        required=True,
    )
    product_uom = fields.Many2one(
        comodel_name="uom.uom",
        string="Unit of measure",
    )
    location_id = fields.Many2one(
        comodel_name="stock.location",
        string="Location",
        required=True,
    )
    product_uom_qty = fields.Float(
        string="Quantity",
        digits=dp.get_precision('Product Unit of Measure'),
    )
    product_qty = fields.Float(
        'Real Quantity',
        compute='_compute_product_quantity',
        inverse='_inverse_product_quantity',
        digits=0,
        store=True,
        help='Quantity in the default UoM of the product',
        readonly=True,
    )
    daily_qty = fields.Float(
        string='Quantity / Day',
        compute='_compute_daily_qty',
    )
    company_id = fields.Many2one(
        comodel_name='res.company',
        string='Company',
        required=True,
        default=lambda self: self.env['res.company']._company_default_get(
            'stock.demand.estimate'
        )
    )

    @api.multi
    @api.depends(
        "manual_duration", "manual_date_from", "manual_date_to",
    )
    def _compute_dates(self):
        today = date.today()
        for rec in self:
            rec.date_from = rec.manual_date_from or today
            if rec.manual_date_to:
                rec.date_to = rec.manual_date_to
                rec.duration = (rec.manual_date_to - rec.date_from).days + 1
            elif rec.manual_duration:
                rec.date_to = rec.date_from + timedelta(
                    days=rec.manual_duration - 1)
                rec.duration = rec.manual_duration
            else:
                rec.date_to = rec.date_from + timedelta(days=1)
                rec.duration = 2

    @api.multi
    @api.depends("product_qty", "duration")
    def _compute_daily_qty(self):
        for rec in self:
            if rec.duration:
                rec.daily_qty = rec.product_qty / rec.duration
            else:
                rec.daily_qty = 0.0

    @api.multi
    @api.depends('product_id', 'product_uom', 'product_uom_qty')
    def _compute_product_quantity(self):
        for rec in self:
            if rec.product_uom:
                rec.product_qty = rec.product_uom._compute_quantity(
                    rec.product_uom_qty, rec.product_id.uom_id
                )
            else:
                rec.product_qty = rec.product_uom_qty

    def _inverse_product_quantity(self):
        raise UserError(_(
            'The requested operation cannot be '
            'processed because of a programming error '
            'setting the `product_qty` field instead '
            'of the `product_uom_qty`.'
        ))

    @api.multi
    def name_get(self):
        res = []
        for rec in self:
            name = "%s - %s: %s - %s" % (
                rec.date_from, rec.date_to,
                rec.product_id.name, rec.location_id.name,
            )
            res.append((rec.id, name))
        return res

    @api.onchange("manual_date_to")
    def _onchange_manual_date_to(self):
        for rec in self:
            if rec.manual_date_from:
                rec.manual_duration = (
                    rec.manual_date_to - rec.manual_date_from).days + 1

    @api.onchange("manual_duration")
    def _onchange_manual_duration(self):
        for rec in self:
            if rec.manual_date_from:
                rec.manual_date_to = rec.manual_date_from + timedelta(
                    days=rec.manual_duration - 1)

    @api.model
    def get_quantity_by_date_range(self, date_start, date_end):
        """To be used in other modules"""
        # Check if the dates overlap with the period
        period_date_start = self.date_from
        period_date_end = self.date_to

        # We need only the periods that overlap
        # the dates introduced by the user.
        if period_date_start <= date_end and period_date_end >= date_start:
            overlap_date_start = max(period_date_start, date_start)
            overlap_date_end = min(period_date_end, date_end)
            days = (abs(overlap_date_end - overlap_date_start)).days + 1
            return days * self.daily_qty
        return 0.0
