# This file is part of Tryton.  The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from dateutil.relativedelta import relativedelta

from trytond.model import (
    DeactivableMixin, ModelSQL, ModelView, fields, sequence_ordered)
from trytond.pool import Pool, PoolMeta


class InvoiceTerm(DeactivableMixin, ModelSQL, ModelView):
    __name__ = 'sale.invoice.term'

    name = fields.Char(
        "Name", required=True, translate=True,
        help="The main identifier of the invoice term.")
    relative_deltas = fields.One2Many(
        'sale.invoice.term.relative_delta', 'term', "Deltas")

    def get_date(self, date=None):
        pool = Pool()
        Date = pool.get('ir.date')
        if date is None:
            date = Date.today()
        for relative_delta in self.relative_deltas:
            date += relative_delta.get()
        return date


class InvoiceTermRelativeDelta(sequence_ordered(), ModelSQL, ModelView):
    __name__ = 'sale.invoice.term.relative_delta'

    term = fields.Many2One(
        'sale.invoice.term', "Invoice Term", required=True, ondelete='CASCADE')
    day = fields.Integer('Day of Month',
        domain=['OR',
            ('day', '=', None),
            [('day', '>=', 1), ('day', '<=', 31)],
            ])
    month = fields.Many2One('ir.calendar.month', "Month")
    weekday = fields.Many2One('ir.calendar.day', "Day of Week")
    months = fields.Integer('Number of Months', required=True)
    weeks = fields.Integer('Number of Weeks', required=True)
    days = fields.Integer('Number of Days', required=True)

    @classmethod
    def __setup__(cls):
        super().__setup__()
        cls.__access__.add('term')

    @classmethod
    def default_months(cls):
        return 0

    @classmethod
    def default_weeks(cls):
        return 0

    @classmethod
    def default_days(cls):
        return 0

    def get(self):
        "Return the relativedelta"
        return relativedelta(
            day=self.day,
            month=int(self.month.index) if self.month else None,
            days=self.days,
            weeks=self.weeks,
            months=self.months,
            weekday=int(self.weekday.index) if self.weekday else None,
            )


class Configuration(metaclass=PoolMeta):
    __name__ = 'sale.configuration'

    sale_invoice_term = fields.MultiValue(fields.Many2One(
            'sale.invoice.term', "Sale Invoice Term"))

    @classmethod
    def multivalue_model(cls, field):
        pool = Pool()
        if field == 'sale_invoice_term':
            return pool.get('sale.configuration.sale_method')
        return super().multivalue_model(field)


class ConfigurationSaleMethod(metaclass=PoolMeta):
    __name__ = 'sale.configuration.sale_method'

    sale_invoice_term = fields.Many2One(
        'sale.invoice.term', "Sale Invoice Term")


class Sale(metaclass=PoolMeta):
    __name__ = 'sale.sale'

    invoice_term = fields.Many2One(
        'sale.invoice.term', "Invoice Term", ondelete='RESTRICT')

    @classmethod
    def default_invoice_term(cls, **pattern):
        pool = Pool()
        Configuration = pool.get('sale.configuration')
        config = Configuration(1)
        invoice_term = config.get_multivalue('sale_invoice_term', **pattern)
        return invoice_term.id if invoice_term else None

    @fields.depends('party', 'company')
    def on_change_party(self):
        super().on_change_party()
        self.invoice_term = self.default_invoice_term(
            company=self.company.id if self.company else None)
        if self.party:
            if self.party.sale_invoice_term:
                self.invoice_term = self.party.sale_invoice_term

    @property
    def _invoice_term_date(self):
        return

    def _get_invoice(self):
        invoice = super()._get_invoice()
        if self.invoice_term:
            invoice.invoice_date = self.invoice_term.get_date(
                date=self._invoice_term_date)
        return invoice

    def _get_invoice_grouping_fields(self, invoice):
        return super()._get_invoice_grouping_fields(invoice) | {
            'invoice_date'}
