# 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 sql import Table

from trytond.config import config
from trytond.model import ModelSQL, ValueMixin, fields
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval, Id
from trytond.transaction import Transaction


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

    default_lot_sequence = fields.MultiValue(
        fields.Many2One(
            'ir.sequence', "Default Lot Sequence",
            domain=[
                ('sequence_type', '=',
                    Id('stock_lot', 'sequence_type_stock_lot')),
                ('company', '=', None),
                ]))


class ConfigurationDefaultLotSequence(ModelSQL, ValueMixin):
    "Product Configuration Default Lot Sequence"
    __name__ = 'product.configuration.default_lot_sequence'
    default_lot_sequence = fields.Many2One(
        'ir.sequence', "Default Lot Sequence",
        domain=[
            ('sequence_type', '=',
                Id('stock_lot', 'sequence_type_stock_lot')),
            ('company', '=', None),
            ])


class Template(metaclass=PoolMeta):
    __name__ = 'product.template'

    lot_required = fields.MultiSelection([
            ('supplier', "Supplier"),
            ('customer', "Customer"),
            ('lost_found', "Lost and Found"),
            ('storage', "Storage"),
            ('production', "Production"),
            ], "Lot Required",
        help='The type of location for which lot is required.',
        states={
            'invisible': ~Eval('type').in_(['goods', 'assets']),
            })
    lot_sequence = fields.Many2One(
        'ir.sequence', "Lot Sequence",
        domain=[
            ('sequence_type', '=', Id('stock_lot', 'sequence_type_stock_lot')),
            ('company', '=', None),
            ],
        states={
            'invisible': ~Eval('type').in_(['goods', 'assets']),
            },
        help="The sequence used to automatically number lots.")

    @classmethod
    def __register__(cls, module):
        connection = Transaction().connection
        cursor = connection.cursor()

        super().__register__(module)

        table_h = cls.__table_handler__(module)
        template_lot_type_table_name = config.get(
            'table', 'product.template-stock.lot.type',
            default='product.template-stock.lot.type' .replace('.', '_'))
        lot_type_table_name = config.get(
            'table', 'stock.lot.type',
            default='stock.lot.type'.replace('.', '_'))

        # Migration from 5.2: fill lot_required
        if (table_h.table_exist(template_lot_type_table_name)
                and table_h.table_exist(lot_type_table_name)):
            table = cls.__table__()
            template_lot_type = Table(template_lot_type_table_name)
            lot_type = Table(lot_type_table_name)

            cursor_select = connection.cursor()
            cursor_select.execute(*template_lot_type.select(
                    template_lot_type.template,
                    distinct_on=template_lot_type.template))
            for template_id, in cursor_select:
                cursor.execute(*template_lot_type
                    .join(lot_type,
                        condition=template_lot_type.type == lot_type.id)
                    .select(
                        lot_type.code,
                        where=template_lot_type.template == template_id))
                value = cls.lot_required.sql_format([t for t, in cursor])
                cursor.execute(*table.update(
                        [table.lot_required], [value],
                        where=table.id == template_id))
            table_h.drop_table('product.template-stock.lot.type',
                template_lot_type_table_name)
            table_h.drop_table('stock.lot.type', lot_type_table_name)

    @classmethod
    def default_lot_sequence(cls, **pattern):
        pool = Pool()
        Configuration = pool.get('product.configuration')
        sequence = Configuration(1).get_multivalue(
            'default_lot_sequence', **pattern)
        return sequence.id if sequence else None


class Product(metaclass=PoolMeta):
    __name__ = 'product.product'

    def lot_is_required(self, from_, to):
        'Is product lot required for move with "from_" and "to" location ?'
        return any(l.type in (self.lot_required or []) for l in [from_, to])

    def create_lot(self):
        pool = Pool()
        Lot = pool.get('stock.lot')
        if self.lot_sequence:
            lot = Lot(product=self)
            try:
                lot.on_change_product()
            except AttributeError:
                pass
            return lot
